Merge pull request #1074 from sharelatex/bg-fail-gracefully-on-copy-project-error

handle failure in parallel copy

GitOrigin-RevId: 67ad5ab9f31689ef66ea2cce75c99c72bf23df41
This commit is contained in:
Brian Gough 2018-10-29 13:44:27 +00:00 committed by sharelatex
parent 707a258d5b
commit 207b0d84c7
2 changed files with 14 additions and 3 deletions

View file

@ -34,10 +34,21 @@ module.exports = ProjectDuplicator =
_copyFiles: (owner_id, newProject, originalProject_id, originalFolder, desFolder, callback)-> _copyFiles: (owner_id, newProject, originalProject_id, originalFolder, desFolder, callback)->
fileRefs = originalFolder.fileRefs or [] fileRefs = originalFolder.fileRefs or []
firstError = null # track first error to exit gracefully from parallel copy
jobs = fileRefs.map (file)-> jobs = fileRefs.map (file)->
return (cb)-> return (cb)->
ProjectEntityUpdateHandler.copyFileFromExistingProjectWithProject newProject, desFolder._id, originalProject_id, file, owner_id, cb return async.setImmediate(cb) if firstError? # skip further copies if an error has occurred
async.parallelLimit jobs, 5, callback ProjectEntityUpdateHandler.copyFileFromExistingProjectWithProject newProject, desFolder._id, originalProject_id, file, owner_id, (err) ->
firstError ||= err if err? # set the error flag if this copy failed
return cb()
# If one of these jobs fails then we wait until all running jobs have
# finished, skipping those which have not started yet. We need to wait
# for all the copy jobs to finish to avoid them writing to the project
# entry in the background while we are deleting it.
async.parallelLimit jobs, 5, (err) ->
return callback(firstError) if firstError?
return callback(err) if err? # shouldn't happen
return callback()
_copyFolderRecursivly: (owner_id, newProject_id, originalProject_id, originalRootDoc, originalFolder, desFolder, docContents, callback)-> _copyFolderRecursivly: (owner_id, newProject_id, originalProject_id, originalRootDoc, originalFolder, desFolder, docContents, callback)->

View file

@ -178,7 +178,7 @@ describe 'ProjectDuplicator', ->
describe 'when there is an error', -> describe 'when there is an error', ->
beforeEach -> beforeEach ->
@rootFolder.fileRefs = [{name:"file0", _id:"file0"}, "BROKEN-FILE"] @rootFolder.fileRefs = [{name:"file0", _id:"file0"}, "BROKEN-FILE", {name:"file1", _id:"file1"}, {name:"file2", _id:"file2"}]
it 'should delete the broken cloned project', (done) -> it 'should delete the broken cloned project', (done) ->
@duplicator.duplicate @owner, @old_project_id, "", (err, newProject)=> @duplicator.duplicate @owner, @old_project_id, "", (err, newProject)=>