mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
switch to single get/set method for getProjectDocs
if project state hasn't changed, return the docs. Otherwise set the hash and return a 409 Conflict response.
This commit is contained in:
parent
f5f516a910
commit
9f3ec72f81
4 changed files with 57 additions and 27 deletions
|
@ -12,7 +12,14 @@ OpRangeNotAvailableError = (message) ->
|
|||
return error
|
||||
OpRangeNotAvailableError.prototype.__proto__ = Error.prototype
|
||||
|
||||
ProjectStateChangedError = (message) ->
|
||||
error = new Error(message)
|
||||
error.name = "ProjectStateChangedError"
|
||||
error.__proto__ = ProjectStateChangedError.prototype
|
||||
return error
|
||||
ProjectStateChangedError.prototype.__proto__ = Error.prototype
|
||||
|
||||
module.exports = Errors =
|
||||
NotFoundError: NotFoundError
|
||||
OpRangeNotAvailableError: OpRangeNotAvailableError
|
||||
|
||||
ProjectStateChangedError: ProjectStateChangedError
|
||||
|
|
|
@ -39,6 +39,7 @@ module.exports = HttpController =
|
|||
|
||||
getProjectDocs: (req, res, next = (error) ->) ->
|
||||
project_id = req.params.project_id
|
||||
projectStateHash = req.query?.state
|
||||
# exclude is string of existing docs "id:version,id:version,..."
|
||||
excludeItems = req.query?.exclude?.split(',') or []
|
||||
logger.log project_id: project_id, exclude: excludeItems, "getting docs via http"
|
||||
|
@ -47,12 +48,16 @@ module.exports = HttpController =
|
|||
for item in excludeItems
|
||||
[id,version] = item?.split(':')
|
||||
excludeVersions[id] = version
|
||||
logger.log {project_id: project_id, excludeVersions: excludeVersions}, "excluding versions"
|
||||
ProjectManager.getProjectDocs project_id, excludeVersions, (error, result) ->
|
||||
logger.log {project_id: project_id, projectStateHash: projectStateHash, excludeVersions: excludeVersions}, "excluding versions"
|
||||
ProjectManager.getProjectDocs project_id, projectStateHash, excludeVersions, (error, result) ->
|
||||
timer.done()
|
||||
return next(error) if error?
|
||||
logger.log project_id: project_id, result: ("#{doc._id}:#{doc.rev}" for doc in result), "got docs via http"
|
||||
res.send result
|
||||
if error instanceof Errors.ProjectStateChangedError
|
||||
res.send 409 # conflict
|
||||
else if error?
|
||||
return next(error)
|
||||
else
|
||||
logger.log project_id: project_id, result: ("#{doc._id}:#{doc.rev}" for doc in result), "got docs via http"
|
||||
res.send result
|
||||
|
||||
setDoc: (req, res, next = (error) ->) ->
|
||||
doc_id = req.params.doc_id
|
||||
|
|
|
@ -3,6 +3,7 @@ DocumentManager = require "./DocumentManager"
|
|||
async = require "async"
|
||||
logger = require "logger-sharelatex"
|
||||
Metrics = require "./Metrics"
|
||||
Errors = require "./Errors"
|
||||
|
||||
module.exports = ProjectManager =
|
||||
flushProjectWithLocks: (project_id, _callback = (error) ->) ->
|
||||
|
@ -57,29 +58,34 @@ module.exports = ProjectManager =
|
|||
else
|
||||
callback(null)
|
||||
|
||||
getProjectDocs: (project_id, excludeVersions = {}, _callback = (error) ->) ->
|
||||
getProjectDocs: (project_id, projectStateHash, excludeVersions = {}, _callback = (error) ->) ->
|
||||
timer = new Metrics.Timer("projectManager.getProjectDocs")
|
||||
callback = (args...) ->
|
||||
timer.done()
|
||||
_callback(args...)
|
||||
|
||||
RedisManager.getDocIdsInProject project_id, (error, doc_ids) ->
|
||||
RedisManager.checkOrSetProjectState project_id, projectStateHash, (error, projectStateChanged) ->
|
||||
return callback(error) if error?
|
||||
jobs = []
|
||||
docs = []
|
||||
for doc_id in doc_ids or []
|
||||
do (doc_id) ->
|
||||
jobs.push (cb) ->
|
||||
# check the doc version first
|
||||
RedisManager.getDocVersion doc_id, (error, version) ->
|
||||
return cb(error) if error?
|
||||
# skip getting the doc if we already have that version
|
||||
return cb() if version is excludeVersions[doc_id]
|
||||
# otherwise get the doc lines from redis
|
||||
RedisManager.getDocLines doc_id, (error, lines) ->
|
||||
return cb(error) if error?
|
||||
docs.push {_id: doc_id, lines: lines, rev: version}
|
||||
cb()
|
||||
async.series jobs, (error) ->
|
||||
# we can't return docs if project structure has changed
|
||||
return callback Errors.ProjectStateChangedError("project state changed") if projectStateChanged
|
||||
# project structure hasn't changed, return doc content from redis
|
||||
RedisManager.getDocIdsInProject project_id, (error, doc_ids) ->
|
||||
return callback(error) if error?
|
||||
callback(null, docs)
|
||||
jobs = []
|
||||
docs = []
|
||||
for doc_id in doc_ids or []
|
||||
do (doc_id) ->
|
||||
jobs.push (cb) ->
|
||||
# check the doc version first
|
||||
RedisManager.getDocVersion doc_id, (error, version) ->
|
||||
return cb(error) if error?
|
||||
# skip getting the doc if we already have that version
|
||||
return cb() if version is excludeVersions[doc_id]
|
||||
# otherwise get the doc lines from redis
|
||||
RedisManager.getDocLines doc_id, (error, lines) ->
|
||||
return cb(error) if error?
|
||||
docs.push {_id: doc_id, lines: lines, rev: version}
|
||||
cb()
|
||||
async.series jobs, (error) ->
|
||||
return callback(error) if error?
|
||||
callback(null, docs)
|
||||
|
|
|
@ -90,10 +90,22 @@ module.exports = RedisManager =
|
|||
return callback(error) if error?
|
||||
multi = rclient.multi()
|
||||
multi.srem keys.docsInProject(project_id:project_id), doc_id
|
||||
if keys.clsiState?
|
||||
multi.del keys.clsiState(project_id:project_id)
|
||||
if keys.projectState?
|
||||
multi.del keys.projectState(project_id:project_id)
|
||||
multi.exec callback
|
||||
|
||||
checkOrSetProjectState: (project_id, newState, callback = (error, stateChanged) ->) ->
|
||||
if keys.projectState?
|
||||
multi = rclient.multi()
|
||||
multi.getset keys.projectState(project_id:project_id), newState
|
||||
multi.expire keys.projectState(project_id:project_id), 30 * minutes
|
||||
multi.exec (error, response) ->
|
||||
return callback(error) if error?
|
||||
logger.log project_id: project_id, newState:newState, oldState: response[0], "checking project state"
|
||||
callback(null, response[0] isnt newState)
|
||||
else
|
||||
callback(null,true)
|
||||
|
||||
getDoc : (project_id, doc_id, callback = (error, lines, version, ranges) ->)->
|
||||
timer = new metrics.Timer("redis.get-doc")
|
||||
multi = rclient.multi()
|
||||
|
|
Loading…
Reference in a new issue