move where lock keys are defined

This commit is contained in:
Hayden Faulds 2018-02-15 13:30:25 +00:00
parent a05d172052
commit 693c8e8c60
7 changed files with 24 additions and 30 deletions

View file

@ -14,8 +14,13 @@ ProjectLocator = require('./ProjectLocator')
SafePath = require './SafePath'
wrapWithLock = (methodWithoutLock) ->
# This lock is used whenever we read or write to an existing project's
# structure. Some operations to project structure cannot be done atomically
# in mongo, this lock is used to prevent reading the structure between two
# parts of a staged update.
methodWithLock = (project_id, args..., callback) ->
LockManager.mongoTransactionLock.runWithLock project_id,
lockKey = ProjectEntityMongoUpdateHandler.getProjectMongoLockKey project_id
LockManager.runWithLock lockKey,
(cb) -> methodWithoutLock project_id, args..., cb
callback
methodWithLock.withoutLock = methodWithoutLock
@ -161,6 +166,9 @@ module.exports = ProjectEntityMongoUpdateHandler = self =
return callback(err)
callback null, folder, parentFolder_id
getProjectMongoLockKey: (project_id) ->
"lock:web:mongoTransaction:{#{project_id}}"
_removeElementFromMongoArray: (model, model_id, path, callback = (err, project) ->)->
conditions = {_id:model_id}
update = {"$unset":{}}

View file

@ -19,8 +19,12 @@ SafePath = require './SafePath'
TpdsUpdateSender = require('../ThirdPartyDataStore/TpdsUpdateSender')
wrapWithLock = (methodWithoutLock) ->
# This lock is used to make sure that the project structure updates are made
# sequentially. In particular the updates must be made in mongo and sent to
# the doc-updater in the same order.
methodWithLock = (project_id, args..., callback) ->
LockManager.sequentialProjectStructureUpdateLock.runWithLock project_id,
lockKey = "lock:web:sequentialProjectStructureUpdateLock:{#{project_id}}"
LockManager.runWithLock lockKey,
(cb) -> methodWithoutLock project_id, args..., cb
callback
methodWithLock.withoutLock = methodWithoutLock

View file

@ -28,7 +28,9 @@ module.exports = ProjectGetter =
return callback("no project_id provided")
if projection?.rootFolder
LockManager.mongoTransactionLock.runWithLock project_id,
ProjectEntityMongoUpdateHandler = require './ProjectEntityMongoUpdateHandler'
lockKey = ProjectEntityMongoUpdateHandler.getProjectMongoLockKey project_id
LockManager.runWithLock lockKey,
(cb) -> ProjectGetter.getProjectWithoutLock project_id, projection, cb
callback
else

View file

@ -9,26 +9,7 @@ module.exports = LockManager =
MAX_LOCK_WAIT_TIME: 10000 # 10s maximum time to spend trying to get the lock
REDIS_LOCK_EXPIRY: 30 # seconds. Time until lock auto expires in redis.
# This lock is used whenever we read or write to an existing project's
# structure. Some operations to project structure cannot be done atomically
# in mongo, this lock is used to prevent reading the structure between two
# parts of a staged update.
#
# This lock should only be called by ProjectEntityHandler and ProjectGetter
mongoTransactionLock:
runWithLock: (project_id, runner = ( (releaseLock = (error) ->) -> ), callback = ( (error) -> )) ->
LockManager._runWithLock "lock:web:mongoTransaction:{#{project_id}}", runner, callback
# This lock is used to make sure that the project structure updates are made
# sequentially. In particular the updates must be made in mongo and sent to
# the doc-updater in the same order.
#
# This lock is generally called at a high level.
sequentialProjectStructureUpdateLock:
runWithLock: (project_id, runner = ( (releaseLock = (error) ->) -> ), callback = ( (error) -> )) ->
LockManager._runWithLock "lock:web:sequentialProjectStructureUpdateLock:{#{project_id}}", runner, callback
_runWithLock: (key, runner = ( (releaseLock = (error) ->) -> ), callback = ( (error) -> )) ->
runWithLock: (key, runner = ( (releaseLock = (error) ->) -> ), callback = ( (error) -> )) ->
LockManager._getLock key, (error) ->
return callback(error) if error?
runner (error1, values...) ->

View file

@ -36,9 +36,8 @@ describe 'ProjectEntityMongoUpdateHandler', ->
"../Cooldown/CooldownManager": @CooldownManager = {}
'../../models/Folder': Folder:@FolderModel
"../../infrastructure/LockManager":@LockManager =
mongoTransactionLock:
runWithLock:
sinon.spy((key, runner, callback) -> runner(callback))
runWithLock:
sinon.spy((key, runner, callback) -> runner(callback))
'../../models/Project': Project:@ProjectModel = {}
'./ProjectEntityHandler': @ProjectEntityHandler = {}
'./ProjectLocator': @ProjectLocator = {}

View file

@ -52,9 +52,8 @@ describe 'ProjectEntityUpdateHandler', ->
'../../models/File': File:@FileModel
'../FileStore/FileStoreHandler':@FileStoreHandler
"../../infrastructure/LockManager":@LockManager =
sequentialProjectStructureUpdateLock:
runWithLock:
sinon.spy((key, runner, callback) -> runner(callback))
runWithLock:
sinon.spy((key, runner, callback) -> runner(callback))
'../../models/Project': Project:@ProjectModel = {}
"./ProjectGetter": @ProjectGetter = {}
'./ProjectLocator': @ProjectLocator = {}

View file

@ -20,8 +20,9 @@ describe "ProjectGetter", ->
"../../models/Project": Project: @Project = {}
"../Collaborators/CollaboratorsHandler": @CollaboratorsHandler = {}
"../../infrastructure/LockManager": @LockManager =
mongoTransactionLock:
runWithLock : sinon.spy((key, runner, callback) -> runner(callback))
'./ProjectEntityMongoUpdateHandler':
lockKey: (project_id) -> project_id
"logger-sharelatex":
err:->
log:->