2020-05-06 10:09:15 +00:00
|
|
|
/* eslint-disable
|
|
|
|
camelcase,
|
|
|
|
handle-callback-err,
|
|
|
|
*/
|
|
|
|
// TODO: This file was created by bulk-decaffeinate.
|
|
|
|
// Fix any style issues and re-enable lint.
|
2020-05-06 10:08:21 +00:00
|
|
|
/*
|
|
|
|
* decaffeinate suggestions:
|
|
|
|
* DS101: Remove unnecessary use of Array.from
|
|
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
|
|
* DS103: Rewrite code to no longer use __guard__
|
|
|
|
* DS201: Simplify complex destructure assignments
|
|
|
|
* DS207: Consider shorter variations of null checks
|
|
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
|
|
*/
|
2020-05-06 10:09:33 +00:00
|
|
|
let ProjectHistoryRedisManager
|
|
|
|
const Settings = require('settings-sharelatex')
|
|
|
|
const projectHistoryKeys = __guard__(
|
|
|
|
Settings.redis != null ? Settings.redis.project_history : undefined,
|
|
|
|
(x) => x.key_schema
|
|
|
|
)
|
2020-11-10 11:32:04 +00:00
|
|
|
const rclient = require('@overleaf/redis-wrapper').createClient(
|
2020-05-06 10:09:33 +00:00
|
|
|
Settings.redis.project_history
|
|
|
|
)
|
|
|
|
const logger = require('logger-sharelatex')
|
|
|
|
const metrics = require('./Metrics')
|
2018-03-09 14:14:14 +00:00
|
|
|
|
2020-05-06 10:09:33 +00:00
|
|
|
module.exports = ProjectHistoryRedisManager = {
|
|
|
|
queueOps(project_id, ...rest) {
|
|
|
|
// Record metric for ops pushed onto queue
|
|
|
|
const adjustedLength = Math.max(rest.length, 1)
|
|
|
|
const ops = rest.slice(0, adjustedLength - 1)
|
|
|
|
const val = rest[adjustedLength - 1]
|
|
|
|
const callback = val != null ? val : function (error, projectUpdateCount) {}
|
|
|
|
for (const op of Array.from(ops)) {
|
|
|
|
metrics.summary('redis.projectHistoryOps', op.length, { status: 'push' })
|
|
|
|
}
|
|
|
|
const multi = rclient.multi()
|
|
|
|
// Push the ops onto the project history queue
|
|
|
|
multi.rpush(
|
|
|
|
projectHistoryKeys.projectHistoryOps({ project_id }),
|
|
|
|
...Array.from(ops)
|
|
|
|
)
|
|
|
|
// To record the age of the oldest op on the queue set a timestamp if not
|
|
|
|
// already present (SETNX).
|
|
|
|
multi.setnx(
|
|
|
|
projectHistoryKeys.projectHistoryFirstOpTimestamp({ project_id }),
|
|
|
|
Date.now()
|
|
|
|
)
|
|
|
|
return multi.exec(function (error, result) {
|
|
|
|
if (error != null) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
// return the number of entries pushed onto the project history queue
|
|
|
|
return callback(null, result[0])
|
|
|
|
})
|
|
|
|
},
|
2018-07-20 09:43:31 +00:00
|
|
|
|
2020-05-06 10:09:33 +00:00
|
|
|
queueRenameEntity(
|
|
|
|
project_id,
|
|
|
|
projectHistoryId,
|
|
|
|
entity_type,
|
|
|
|
entity_id,
|
|
|
|
user_id,
|
|
|
|
projectUpdate,
|
|
|
|
callback
|
|
|
|
) {
|
|
|
|
projectUpdate = {
|
|
|
|
pathname: projectUpdate.pathname,
|
|
|
|
new_pathname: projectUpdate.newPathname,
|
|
|
|
meta: {
|
|
|
|
user_id,
|
|
|
|
ts: new Date()
|
|
|
|
},
|
|
|
|
version: projectUpdate.version,
|
|
|
|
projectHistoryId
|
|
|
|
}
|
|
|
|
projectUpdate[entity_type] = entity_id
|
2018-03-09 14:14:14 +00:00
|
|
|
|
2020-05-06 10:09:33 +00:00
|
|
|
logger.log(
|
|
|
|
{ project_id, projectUpdate },
|
|
|
|
'queue rename operation to project-history'
|
|
|
|
)
|
|
|
|
const jsonUpdate = JSON.stringify(projectUpdate)
|
2018-03-09 14:14:14 +00:00
|
|
|
|
2020-05-06 10:09:33 +00:00
|
|
|
return ProjectHistoryRedisManager.queueOps(project_id, jsonUpdate, callback)
|
|
|
|
},
|
2018-03-09 14:14:14 +00:00
|
|
|
|
2020-05-06 10:09:33 +00:00
|
|
|
queueAddEntity(
|
|
|
|
project_id,
|
|
|
|
projectHistoryId,
|
|
|
|
entity_type,
|
|
|
|
entitiy_id,
|
|
|
|
user_id,
|
|
|
|
projectUpdate,
|
|
|
|
callback
|
|
|
|
) {
|
|
|
|
if (callback == null) {
|
|
|
|
callback = function (error) {}
|
|
|
|
}
|
|
|
|
projectUpdate = {
|
|
|
|
pathname: projectUpdate.pathname,
|
|
|
|
docLines: projectUpdate.docLines,
|
|
|
|
url: projectUpdate.url,
|
|
|
|
meta: {
|
|
|
|
user_id,
|
|
|
|
ts: new Date()
|
|
|
|
},
|
|
|
|
version: projectUpdate.version,
|
|
|
|
projectHistoryId
|
|
|
|
}
|
|
|
|
projectUpdate[entity_type] = entitiy_id
|
2018-03-09 14:14:14 +00:00
|
|
|
|
2020-05-06 10:09:33 +00:00
|
|
|
logger.log(
|
|
|
|
{ project_id, projectUpdate },
|
|
|
|
'queue add operation to project-history'
|
|
|
|
)
|
|
|
|
const jsonUpdate = JSON.stringify(projectUpdate)
|
2018-03-09 14:14:14 +00:00
|
|
|
|
2020-05-06 10:09:33 +00:00
|
|
|
return ProjectHistoryRedisManager.queueOps(project_id, jsonUpdate, callback)
|
|
|
|
},
|
2018-03-09 14:14:14 +00:00
|
|
|
|
2020-05-06 10:09:33 +00:00
|
|
|
queueResyncProjectStructure(
|
|
|
|
project_id,
|
|
|
|
projectHistoryId,
|
|
|
|
docs,
|
|
|
|
files,
|
|
|
|
callback
|
|
|
|
) {
|
|
|
|
logger.log({ project_id, docs, files }, 'queue project structure resync')
|
|
|
|
const projectUpdate = {
|
|
|
|
resyncProjectStructure: { docs, files },
|
|
|
|
projectHistoryId,
|
|
|
|
meta: {
|
|
|
|
ts: new Date()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const jsonUpdate = JSON.stringify(projectUpdate)
|
|
|
|
return ProjectHistoryRedisManager.queueOps(project_id, jsonUpdate, callback)
|
|
|
|
},
|
2018-03-09 14:14:14 +00:00
|
|
|
|
2020-05-06 10:09:33 +00:00
|
|
|
queueResyncDocContent(
|
|
|
|
project_id,
|
|
|
|
projectHistoryId,
|
|
|
|
doc_id,
|
|
|
|
lines,
|
|
|
|
version,
|
|
|
|
pathname,
|
|
|
|
callback
|
|
|
|
) {
|
|
|
|
logger.log(
|
|
|
|
{ project_id, doc_id, lines, version, pathname },
|
|
|
|
'queue doc content resync'
|
|
|
|
)
|
|
|
|
const projectUpdate = {
|
|
|
|
resyncDocContent: {
|
|
|
|
content: lines.join('\n'),
|
|
|
|
version
|
|
|
|
},
|
|
|
|
projectHistoryId,
|
|
|
|
path: pathname,
|
|
|
|
doc: doc_id,
|
|
|
|
meta: {
|
|
|
|
ts: new Date()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const jsonUpdate = JSON.stringify(projectUpdate)
|
|
|
|
return ProjectHistoryRedisManager.queueOps(project_id, jsonUpdate, callback)
|
|
|
|
}
|
|
|
|
}
|
2020-05-06 10:08:21 +00:00
|
|
|
|
|
|
|
function __guard__(value, transform) {
|
2020-05-06 10:09:33 +00:00
|
|
|
return typeof value !== 'undefined' && value !== null
|
|
|
|
? transform(value)
|
|
|
|
: undefined
|
|
|
|
}
|