Skip to content

Commit a326bd2

Browse files
author
Shivam Pandey
authored
Merge pull request #45 from causecode/move-files-to-new-cdn-changes
Move files to new CDN changes
2 parents 519b436 + 4f3b085 commit a326bd2

File tree

5 files changed

+153
-2
lines changed

5 files changed

+153
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# File-Uploader Plugin (Latest 4.0.3)
1+
# File-Uploader Plugin (Latest 4.0.4)
22

33
[![Maintainability](https://api.codeclimate.com/v1/badges/13bfee73c29ecd2ea4b2/maintainability)](https://codeclimate.com/github/causecode/grails-file-uploader/maintainability)
44
[![Test Coverage](https://api.codeclimate.com/v1/badges/13bfee73c29ecd2ea4b2/test_coverage)](https://codeclimate.com/github/causecode/grails-file-uploader/test_coverage)

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ buildscript {
1515
}
1616
}
1717

18-
version "4.0.3"
18+
version "4.0.4"
1919
group "com.causecode.plugins"
2020

2121
apply plugin: "idea"

changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# ChangeLog
22

3+
## Version 4.0.4 [24-04-2019]
4+
35
## Version 4.0.3 [28-03-2019]
46

57
### Fixed

grails-app/services/com/causecode/fileuploader/FileUploaderService.groovy

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,46 @@ class FileUploaderService {
414414
return Holders.flatConfig["fileuploader.groups.${fileGroup}.makePublic"] ? true : false
415415
}
416416

417+
/**
418+
* This methods move all the instances of {@link UFile} which are not local to the destination {@link CDNProvider}.
419+
* The migration from one CDN to another follows below steps.
420+
* 1. A copy of {@link File} from the source CDN {@link UFile} instance.
421+
* 2. Upload it to the destination CDN.
422+
* 3. Update the respective {@link UFile} instance.
423+
* 4. Creates an instance of {@link UFileMoveHistory} which contains the {@link UFile} move history.
424+
*
425+
* @param toCDNProvider {@link CDNProvider} - Target destination CDN provider.
426+
* @param makePublic {@link boolean} - All the URLs either public or signed.
427+
* @return {@link boolean} Based on the successful move.
428+
*/
429+
boolean moveToNewCDN(CDNProvider toCDNProvider, boolean makePublic = false) {
430+
if (!toCDNProvider) {
431+
log.debug 'Please provide the target CDN provider name.'
432+
433+
return false
434+
}
435+
436+
log.debug "Migration from source CDN to target ${toCDNProvider.name()} has been started..."
437+
438+
List<UFile> uFileList, uFilesUploadFailuresList = []
439+
int offset = 0
440+
441+
while ((uFileList = UFile.createCriteria().list(max: 500, offset: offset) {
442+
ne('type', CDNProvider.LOCAL)
443+
}).size()) {
444+
uFilesUploadFailuresList.addAll(moveFilesToCDN(uFileList, toCDNProvider, makePublic))
445+
446+
log.debug "Moved ${uFileList.size()} files to new CDN and failed count: ${uFilesUploadFailuresList.size()}"
447+
448+
offset += 500
449+
}
450+
451+
log.debug "Successfully moved files to new ${toCDNProvider.toString()} CDN and failed to upload total files" +
452+
": ${uFilesUploadFailuresList.size()}"
453+
454+
return true
455+
}
456+
417457
/**
418458
* Moves all UFiles stored at any CDN provider to the given CDN provider. Does not touch UFiles stored locally.
419459
* Needs to be executed only once.

src/test/groovy/com/causecode/fileuploader/FileUploaderServiceSpec.groovy

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.causecode.fileuploader.util.checksum.Algorithm
55
import com.causecode.fileuploader.util.checksum.exceptions.DuplicateFileException
66
import grails.buildtestdata.BuildDataTest
77
import grails.buildtestdata.mixin.Build
8+
import grails.gorm.CriteriaBuilder
89
import grails.testing.services.ServiceUnitTest
910
import grails.util.Holders
1011
import groovy.json.JsonBuilder
@@ -36,6 +37,23 @@ class FileUploaderServiceSpec extends BaseFileUploaderServiceSpecSetup implement
3637
service.providerService = providerService
3738
}
3839

40+
@SuppressWarnings('MapAsMethodParameter')
41+
void mockCreateCriteria(List<Object> resultList) {
42+
GroovyMock(UFile, global: true)
43+
CriteriaBuilder criteriaBuilder = Mock()
44+
45+
criteriaBuilder.list(_, _) >> { Map params, Closure closure ->
46+
JsonBuilder jsonBuilder = new JsonBuilder()
47+
jsonBuilder closure
48+
49+
return resultList
50+
} >> {
51+
return []
52+
}
53+
54+
UFile.createCriteria() >> criteriaBuilder
55+
}
56+
3957
void "test isPublicGroup for various file groups"() {
4058
expect: 'Following conditions should pass'
4159
service.isPublicGroup('user') == true
@@ -864,4 +882,95 @@ class FileUploaderServiceSpec extends BaseFileUploaderServiceSpecSetup implement
864882
StorageConfigurationException exception = thrown(StorageConfigurationException)
865883
exception.message == 'Container name not defined in the Config. Please define one.'
866884
}
885+
886+
void "test moveToNewCDN method for successfully moving the files to the target CDN provider"() {
887+
given: 'An instance of UFile'
888+
UFile uFileOne = UFile.build(path: '/tmp/test1.txt', provider: CDNProvider.GOOGLE, fileGroup: 'testGoogle')
889+
UFile uFileTwo = UFile.build(path: '/tmp/test2.txt', provider: CDNProvider.GOOGLE, fileGroup: 'testGoogle')
890+
891+
and: 'Mocked the createCriteria method to return the UFiles list'
892+
mockCreateCriteria([uFileOne, uFileTwo])
893+
894+
and: 'Mocked the moveFilesToCDN method to move the files to source CDN provider successfully'
895+
service.metaClass.static.moveFilesToCDN = { List<UFile> list, CDNProvider provider, boolean makePublic ->
896+
list.each { UFile file ->
897+
file.provider = CDNProvider.AMAZON
898+
file.save()
899+
}
900+
}
901+
902+
when: 'moveToNewCDN method is called'
903+
assert uFileOne.provider == CDNProvider.GOOGLE
904+
assert uFileTwo.provider == CDNProvider.GOOGLE
905+
906+
boolean status = service.moveToNewCDN(CDNProvider.AMAZON, false)
907+
908+
then: 'it should return true and all the UFile providers must be changed to target CDN'
909+
status
910+
uFileOne.provider == CDNProvider.AMAZON
911+
uFileTwo.provider == CDNProvider.AMAZON
912+
}
913+
914+
void "test moveToNewCDN method for the failure case when we move files to target CDN"() {
915+
given: 'An instance of UFile'
916+
UFile uFileOne = UFile.build(path: '/tmp/test1.txt', provider: CDNProvider.GOOGLE, fileGroup: 'testGoogle')
917+
UFile uFileTwo = UFile.build(path: '/tmp/test2.txt', provider: CDNProvider.GOOGLE, fileGroup: 'testGoogle')
918+
919+
and: 'Mocked the createCriteria method to return the UFiles list'
920+
mockCreateCriteria([uFileOne, uFileTwo])
921+
922+
and: 'Mocked the moveFilesToCDN method to return the list of failed documents'
923+
service.metaClass.static.moveFilesToCDN = { List<UFile> list, CDNProvider provider, boolean makePublic ->
924+
list.each { UFile file ->
925+
UFileMoveHistory.build(ufile: file, fromCDN: file.provider, toCDN: provider, status: MoveStatus.FAILURE,
926+
details: 'failed to move.')
927+
return false
928+
}
929+
930+
return list
931+
}
932+
933+
when: 'moveToNewCDN method is called'
934+
boolean status = service.moveToNewCDN(CDNProvider.AMAZON, false)
935+
936+
then: 'it should return true and all the UFile providers must not be changed'
937+
status
938+
uFileOne.provider == CDNProvider.GOOGLE
939+
uFileTwo.provider == CDNProvider.GOOGLE
940+
UFileMoveHistory.count() == 2
941+
}
942+
943+
void "test moveToNewCDN method for amazon when exception occurs in a file URL"() {
944+
given: 'An instance of UFile and File'
945+
UFile uFileInstance = UFile.build(path: '/tmp/test.txt', provider: CDNProvider.GOOGLE, fileGroup: 'testGoogle')
946+
File fileInstance = getFileInstance('/tmp/test.txt')
947+
948+
and: 'Mocked method'
949+
service.metaClass.getFileFromURL = { String url, String filename ->
950+
throw new IOException('Error getting file from URL')
951+
}
952+
953+
and: 'Mocked Amazon provider instance'
954+
mockGetProviderInstance(CDNProvider.AMAZON.name())
955+
956+
and: 'Mocked the uploadFile method of amazon'
957+
mockUploadFileMethod(true)
958+
959+
when: 'moveFilesToCDN method is called'
960+
service.moveToNewCDN(CDNProvider.AMAZON, true)
961+
962+
then: 'File won\'t be moved'
963+
uFileInstance.provider == CDNProvider.GOOGLE
964+
965+
cleanup:
966+
fileInstance.delete()
967+
}
968+
969+
void "test moveToNewCDN method is called with null CDN provider name"() {
970+
when: 'moveToNewCDN method is called'
971+
boolean status = service.moveToNewCDN(null, false)
972+
973+
then: 'it should return false'
974+
!status
975+
}
867976
}

0 commit comments

Comments
 (0)