Use rwlock together with lockfile

Select app to kill from DB within lock (otherwise, if some other part kills and restarts the app, the
containerId will have changed and the real container will not be removed).
This commit is contained in:
Pablo Carranza Vélez 2015-08-21 19:48:07 +00:00
parent d1b317399e
commit c7c4aed746
2 changed files with 38 additions and 22 deletions

View File

@ -67,11 +67,11 @@ module.exports = (secret) ->
utils.mixpanelTrack('Purge /data', appId)
if !appId?
return res.status(400).send('Missing app id')
Promise.using application.lockUpdates(app), ->
knex('app').select().where({ appId })
.then ([ app ]) ->
if !app?
throw new Error('App not found')
Promise.using application.lockUpdates(app), ->
application.kill(app)
.then ->
new Promise (resolve, reject) ->

View File

@ -251,13 +251,19 @@ exports.unlockAndStart = unlockAndStart = (app) ->
.then ->
start(app)
exports.lockUpdates = lockUpdates = (app, force) ->
Promise.try ->
exports.lockUpdates = lockUpdates = do ->
_lock = new Lock()
_writeLock = Promise.promisify(_lock.async.writeLock)
return (app, force) ->
_writeLock(lockPath(app))
.tap ->
lockFile.unlockAsync(lockPath(app)) if force == true
.then ->
.tap ->
lockFile.lockAsync(lockPath(app))
.disposer ->
.disposer (release) ->
lockFile.unlockAsync(lockPath(app))
.then ->
release()
joinErrorMessages = (failures) ->
s = if failures.length > 1 then 's' else ''
@ -354,7 +360,13 @@ exports.update = update = (force) ->
# Then delete all the ones to remove in one go
Promise.map toBeRemoved, (appId) ->
Promise.using lockUpdates(apps[appId], force), ->
kill(apps[appId])
# We get the app from the DB again in case someone restarted it
# (which would have changed its containerId)
knex('app').select().where({ appId })
.then ([ app ]) ->
if !app?
throw new Error('App not found')
kill(app)
.then ->
knex('app').where('appId', appId).delete()
.catch (err) ->
@ -372,6 +384,10 @@ exports.update = update = (force) ->
app = remoteApps[appId]
logSystemEvent(logTypes.updateApp, app) if localApp.imageId == app.imageId
Promise.using lockUpdates(localApp, force), ->
knex('app').select().where({ appId })
.then ([ localApp ]) ->
if !localApp?
throw new Error('App not found')
kill(localApp)
.then ->
start(app)