/* eslint-disable camelcase, handle-callback-err, */ // 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 * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ let ProjectPersistenceManager const UrlCache = require('./UrlCache') const CompileManager = require('./CompileManager') const db = require('./db') const dbQueue = require('./DbQueue') const async = require('async') const logger = require('logger-sharelatex') const oneDay = 24 * 60 * 60 * 1000 const Settings = require('settings-sharelatex') const diskusage = require('diskusage') module.exports = ProjectPersistenceManager = { EXPIRY_TIMEOUT: Settings.project_cache_length_ms || oneDay * 2.5, refreshExpiryTimeout(callback) { if (callback == null) { callback = function(error) {} } diskusage.check('/', function(err, stats) { if (err) { logger.err({ err: err }, 'error getting disk usage') return callback(err) } const lowDisk = stats.available / stats.total < 0.1 const lowerExpiry = ProjectPersistenceManager.EXPIRY_TIMEOUT * 0.9 if (lowDisk && Settings.project_cache_length_ms / 2 < lowerExpiry) { logger.warn( { stats: stats }, 'disk running low on space, modifying EXPIRY_TIMEOUT' ) ProjectPersistenceManager.EXPIRY_TIMEOUT = lowerExpiry } callback() }) }, markProjectAsJustAccessed(project_id, callback) { if (callback == null) { callback = function(error) {} } const job = cb => db.Project.findOrCreate({ where: { project_id } }) .spread((project, created) => project .update({ lastAccessed: new Date() }) .then(() => cb()) .error(cb) ) .error(cb) return dbQueue.queue.push(job, callback) }, clearExpiredProjects(callback) { if (callback == null) { callback = function(error) {} } return ProjectPersistenceManager._findExpiredProjectIds(function( error, project_ids ) { if (error != null) { return callback(error) } logger.log({ project_ids }, 'clearing expired projects') const jobs = Array.from(project_ids || []).map(project_id => (project_id => callback => ProjectPersistenceManager.clearProjectFromCache(project_id, function( err ) { if (err != null) { logger.error({ err, project_id }, 'error clearing project') } return callback() }))(project_id) ) return async.series(jobs, function(error) { if (error != null) { return callback(error) } return CompileManager.clearExpiredProjects( ProjectPersistenceManager.EXPIRY_TIMEOUT, error => callback() ) }) }) }, // ignore any errors from deleting directories clearProject(project_id, user_id, callback) { if (callback == null) { callback = function(error) {} } logger.log({ project_id, user_id }, 'clearing project for user') return CompileManager.clearProject(project_id, user_id, function(error) { if (error != null) { return callback(error) } return ProjectPersistenceManager.clearProjectFromCache( project_id, function(error) { if (error != null) { return callback(error) } return callback() } ) }) }, clearProjectFromCache(project_id, callback) { if (callback == null) { callback = function(error) {} } logger.log({ project_id }, 'clearing project from cache') return UrlCache.clearProject(project_id, function(error) { if (error != null) { logger.err({ error, project_id }, 'error clearing project from cache') return callback(error) } return ProjectPersistenceManager._clearProjectFromDatabase( project_id, function(error) { if (error != null) { logger.err( { error, project_id }, 'error clearing project from database' ) } return callback(error) } ) }) }, _clearProjectFromDatabase(project_id, callback) { if (callback == null) { callback = function(error) {} } logger.log({ project_id }, 'clearing project from database') const job = cb => db.Project.destroy({ where: { project_id } }) .then(() => cb()) .error(cb) return dbQueue.queue.push(job, callback) }, _findExpiredProjectIds(callback) { if (callback == null) { callback = function(error, project_ids) {} } const job = function(cb) { const keepProjectsFrom = new Date( Date.now() - ProjectPersistenceManager.EXPIRY_TIMEOUT ) const q = {} q[db.op.lt] = keepProjectsFrom return db.Project.findAll({ where: { lastAccessed: q } }) .then(projects => cb( null, projects.map(project => project.project_id) ) ) .error(cb) } return dbQueue.queue.push(job, callback) } } logger.log( { EXPIRY_TIMEOUT: ProjectPersistenceManager.EXPIRY_TIMEOUT }, 'project assets kept timeout' )