overleaf/services/web/app/src/Features/Compile/ClsiStateManager.js

82 lines
2.8 KiB
JavaScript
Raw Normal View History

/* eslint-disable
node/handle-callback-err,
max-len,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS205: Consider reworking code to avoid use of IIFEs
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
let ClsiStateManager
const Settings = require('@overleaf/settings')
const logger = require('@overleaf/logger')
const crypto = require('crypto')
const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
// The "state" of a project is a hash of the relevant attributes in the
// project object in this case we only need the rootFolder.
//
// The idea is that it will change if any doc or file is
// created/renamed/deleted, and also if the content of any file (not
// doc) changes.
//
// When the hash changes the full set of files on the CLSI will need to
// be updated. If it doesn't change then we can overwrite changed docs
// in place on the clsi, getting them from the docupdater.
//
// The docupdater is responsible for setting the key in redis, and
// unsetting it if it removes any documents from the doc updater.
const buildState = s =>
crypto.createHash('sha1').update(s, 'utf8').digest('hex')
module.exports = ClsiStateManager = {
computeHash(project, options, callback) {
if (callback == null) {
callback = function () {}
}
return ProjectEntityHandler.getAllEntitiesFromProject(
project,
function (err, docs, files) {
const fileList = Array.from(files || []).map(
f => `${f.file._id}:${f.file.rev}:${f.file.created}:${f.path}`
)
const docList = Array.from(docs || []).map(
d => `${d.doc._id}:${d.path}`
)
const sortedEntityList = [
...Array.from(docList),
...Array.from(fileList),
].sort()
// ignore the isAutoCompile options as it doesn't affect the
// output, but include all other options e.g. draft
const optionsList = (() => {
const result = []
const object = options || {}
for (const key in object) {
const value = object[key]
if (!['isAutoCompile'].includes(key)) {
result.push(`option ${key}:${value}`)
}
}
return result
})()
const sortedOptionsList = optionsList.sort()
const hash = buildState(
[
...Array.from(sortedEntityList),
...Array.from(sortedOptionsList),
].join('\n')
)
return callback(null, hash)
}
)
},
}