mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge pull request #16428 from overleaf/jpa-clsi-replace-fs-extra
[clsi] replace fs-extra to avoid excess syscalls GitOrigin-RevId: cbc8ec01b8ac9fd973e86a6d763c8f599323db94
This commit is contained in:
parent
f6b7b84e88
commit
b4b369fea5
8 changed files with 90 additions and 55 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -25690,6 +25690,7 @@
|
|||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
||||
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
|
@ -43509,7 +43510,6 @@
|
|||
"diskusage": "^1.1.3",
|
||||
"dockerode": "^3.1.0",
|
||||
"express": "^4.18.2",
|
||||
"fs-extra": "^10.0.0",
|
||||
"lockfile": "^1.0.4",
|
||||
"lodash": "^4.17.21",
|
||||
"p-limit": "^3.1.0",
|
||||
|
@ -53819,7 +53819,6 @@
|
|||
"diskusage": "^1.1.3",
|
||||
"dockerode": "^3.1.0",
|
||||
"express": "^4.18.2",
|
||||
"fs-extra": "^10.0.0",
|
||||
"lockfile": "^1.0.4",
|
||||
"lodash": "^4.17.21",
|
||||
"mocha": "^10.2.0",
|
||||
|
@ -69135,6 +69134,7 @@
|
|||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
||||
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
const childProcess = require('child_process')
|
||||
const fsPromises = require('fs/promises')
|
||||
const fse = require('fs-extra')
|
||||
const os = require('os')
|
||||
const Path = require('path')
|
||||
const { callbackify, promisify } = require('util')
|
||||
|
@ -51,7 +50,7 @@ async function doCompileWithLock(request) {
|
|||
// use a .project-lock file in the compile directory to prevent
|
||||
// simultaneous compiles
|
||||
const lockFile = Path.join(compileDir, '.project-lock')
|
||||
await fse.ensureDir(compileDir)
|
||||
await fsPromises.mkdir(compileDir, { recursive: true })
|
||||
const lock = await LockManager.acquire(lockFile)
|
||||
try {
|
||||
return await doCompile(request)
|
||||
|
@ -378,7 +377,7 @@ async function clearExpiredProjects(maxCacheAgeMs) {
|
|||
const age = now - stats.mtime
|
||||
const hasExpired = age > maxCacheAgeMs
|
||||
if (hasExpired) {
|
||||
await fse.remove(dir)
|
||||
await fsPromises.rm(dir, { force: true, recursive: true })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -519,7 +518,7 @@ async function wordcount(projectId, userId, filename, image) {
|
|||
const compileName = getCompileName(projectId, userId)
|
||||
const compileGroup = 'wordcount'
|
||||
try {
|
||||
await fse.ensureDir(compileDir)
|
||||
await fsPromises.mkdir(compileDir, { recursive: true })
|
||||
} catch (err) {
|
||||
throw OError.tag(err, 'error ensuring dir for wordcount', {
|
||||
projectId,
|
||||
|
|
|
@ -2,7 +2,6 @@ let OutputCacheManager
|
|||
const { callbackify, promisify } = require('util')
|
||||
const async = require('async')
|
||||
const fs = require('fs')
|
||||
const fse = require('fs-extra')
|
||||
const Path = require('path')
|
||||
const logger = require('@overleaf/logger')
|
||||
const _ = require('lodash')
|
||||
|
@ -240,7 +239,7 @@ module.exports = OutputCacheManager = {
|
|||
}
|
||||
|
||||
// make the new cache directory
|
||||
fse.ensureDir(cacheDir, function (err) {
|
||||
fs.mkdir(cacheDir, { recursive: true }, function (err) {
|
||||
if (err) {
|
||||
logger.error(
|
||||
{ err, directory: cacheDir },
|
||||
|
@ -250,6 +249,8 @@ module.exports = OutputCacheManager = {
|
|||
} else {
|
||||
// copy all the output files into the new cache directory
|
||||
const results = []
|
||||
const dirCache = new Set()
|
||||
dirCache.add(cacheDir)
|
||||
async.mapSeries(
|
||||
outputFiles,
|
||||
function (file, cb) {
|
||||
|
@ -281,7 +282,7 @@ module.exports = OutputCacheManager = {
|
|||
if (!shouldCopy) {
|
||||
return cb()
|
||||
}
|
||||
OutputCacheManager._copyFile(src, dst, function (err) {
|
||||
OutputCacheManager._copyFile(src, dst, dirCache, err => {
|
||||
if (err) {
|
||||
return cb(err)
|
||||
}
|
||||
|
@ -298,7 +299,7 @@ module.exports = OutputCacheManager = {
|
|||
// pass back the original files if we encountered *any* error
|
||||
callback(err, outputFiles)
|
||||
// clean up the directory we just created
|
||||
fse.remove(cacheDir, function (err) {
|
||||
fs.rm(cacheDir, { force: true, recursive: true }, function (err) {
|
||||
if (err) {
|
||||
return logger.error(
|
||||
{ err, dir: cacheDir },
|
||||
|
@ -447,7 +448,7 @@ module.exports = OutputCacheManager = {
|
|||
},
|
||||
|
||||
ensureContentDir(contentRoot, callback) {
|
||||
fse.ensureDir(contentRoot, function (err) {
|
||||
fs.mkdir(contentRoot, { recursive: true }, function (err) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
@ -466,7 +467,7 @@ module.exports = OutputCacheManager = {
|
|||
return callback(err)
|
||||
}
|
||||
const contentDir = Path.join(contentRoot, contentId)
|
||||
fse.ensureDir(contentDir, function (err) {
|
||||
fs.mkdir(contentDir, { recursive: true }, function (err) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
@ -485,10 +486,12 @@ module.exports = OutputCacheManager = {
|
|||
buildId
|
||||
)
|
||||
logger.debug({ dir: archiveDir }, 'archiving log files for project')
|
||||
fse.ensureDir(archiveDir, function (err) {
|
||||
fs.mkdir(archiveDir, { recursive: true }, function (err) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
const dirCache = new Set()
|
||||
dirCache.add(archiveDir)
|
||||
async.mapSeries(
|
||||
outputFiles,
|
||||
function (file, cb) {
|
||||
|
@ -510,7 +513,7 @@ module.exports = OutputCacheManager = {
|
|||
if (!shouldArchive) {
|
||||
return cb()
|
||||
}
|
||||
OutputCacheManager._copyFile(src, dst, cb)
|
||||
OutputCacheManager._copyFile(src, dst, dirCache, cb)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
@ -523,7 +526,7 @@ module.exports = OutputCacheManager = {
|
|||
expireOutputFiles(outputDir, options, callback) {
|
||||
// look in compileDir for build dirs and delete if > N or age of mod time > T
|
||||
const cleanupAll = cb => {
|
||||
fse.remove(outputDir, err => {
|
||||
fs.rm(outputDir, { force: true, recursive: true }, err => {
|
||||
if (err) {
|
||||
return cb(err)
|
||||
}
|
||||
|
@ -582,13 +585,17 @@ module.exports = OutputCacheManager = {
|
|||
}
|
||||
|
||||
const removeDir = (dir, cb) =>
|
||||
fse.remove(Path.join(cacheRoot, dir), function (err, result) {
|
||||
logger.debug({ cache: cacheRoot, dir }, 'removed expired cache dir')
|
||||
if (err) {
|
||||
logger.error({ err, dir }, 'cache remove error')
|
||||
fs.rm(
|
||||
Path.join(cacheRoot, dir),
|
||||
{ force: true, recursive: true },
|
||||
function (err, result) {
|
||||
logger.debug({ cache: cacheRoot, dir }, 'removed expired cache dir')
|
||||
if (err) {
|
||||
logger.error({ err, dir }, 'cache remove error')
|
||||
}
|
||||
cb(err, result)
|
||||
}
|
||||
cb(err, result)
|
||||
})
|
||||
)
|
||||
async.eachSeries(
|
||||
toRemove,
|
||||
(dir, cb) => removeDir(dir, cb),
|
||||
|
@ -637,28 +644,53 @@ module.exports = OutputCacheManager = {
|
|||
})
|
||||
},
|
||||
|
||||
_copyFile(src, dst, callback) {
|
||||
// copy output file into the cache
|
||||
fse.copy(src, dst, function (err) {
|
||||
if (err?.code === 'ENOENT') {
|
||||
logger.warn(
|
||||
{ err, file: src },
|
||||
'file has disappeared when copying to build cache'
|
||||
)
|
||||
callback(err, false)
|
||||
} else if (err) {
|
||||
logger.error({ err, src, dst }, 'copy error for file in cache')
|
||||
callback(err)
|
||||
} else {
|
||||
if (Settings.clsi?.optimiseInDocker) {
|
||||
// don't run any optimisations on the pdf when they are done
|
||||
// in the docker container
|
||||
callback()
|
||||
} else {
|
||||
// call the optimiser for the file too
|
||||
OutputFileOptimiser.optimiseFile(src, dst, callback)
|
||||
_ensureParentExists(dst, dirCache, callback) {
|
||||
let parent = Path.dirname(dst)
|
||||
if (dirCache.has(parent)) {
|
||||
callback()
|
||||
} else {
|
||||
fs.mkdir(parent, { recursive: true }, err => {
|
||||
if (err) return callback(err)
|
||||
while (!dirCache.has(parent)) {
|
||||
dirCache.add(parent)
|
||||
parent = Path.dirname(parent)
|
||||
}
|
||||
callback()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
_copyFile(src, dst, dirCache, callback) {
|
||||
OutputCacheManager._ensureParentExists(dst, dirCache, err => {
|
||||
if (err) {
|
||||
logger.warn(
|
||||
{ err, dst },
|
||||
'creating parent directory in output cache failed'
|
||||
)
|
||||
return callback(err, false)
|
||||
}
|
||||
// copy output file into the cache
|
||||
fs.copyFile(src, dst, function (err) {
|
||||
if (err?.code === 'ENOENT') {
|
||||
logger.warn(
|
||||
{ err, file: src },
|
||||
'file has disappeared when copying to build cache'
|
||||
)
|
||||
callback(err, false)
|
||||
} else if (err) {
|
||||
logger.error({ err, src, dst }, 'copy error for file in cache')
|
||||
callback(err)
|
||||
} else {
|
||||
if (Settings.clsi?.optimiseInDocker) {
|
||||
// don't run any optimisations on the pdf when they are done
|
||||
// in the docker container
|
||||
callback()
|
||||
} else {
|
||||
// call the optimiser for the file too
|
||||
OutputFileOptimiser.optimiseFile(src, dst, callback)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
const UrlFetcher = require('./UrlFetcher')
|
||||
const Settings = require('@overleaf/settings')
|
||||
const fs = require('fs')
|
||||
const fse = require('fs-extra')
|
||||
const Path = require('path')
|
||||
const { callbackify } = require('util')
|
||||
|
||||
|
@ -32,7 +31,10 @@ function getCachePath(projectId, url, lastModified) {
|
|||
}
|
||||
|
||||
async function clearProject(projectId) {
|
||||
await fse.remove(getProjectDir(projectId))
|
||||
await fs.promises.rm(getProjectDir(projectId), {
|
||||
force: true,
|
||||
recursive: true,
|
||||
})
|
||||
}
|
||||
|
||||
async function createProjectDir(projectId) {
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
"diskusage": "^1.1.3",
|
||||
"dockerode": "^3.1.0",
|
||||
"express": "^4.18.2",
|
||||
"fs-extra": "^10.0.0",
|
||||
"lockfile": "^1.0.4",
|
||||
"lodash": "^4.17.21",
|
||||
"p-limit": "^3.1.0",
|
||||
|
|
|
@ -16,7 +16,6 @@ const Client = require('./helpers/Client')
|
|||
const fetch = require('node-fetch')
|
||||
const { pipeline } = require('stream')
|
||||
const fs = require('fs')
|
||||
const fsExtra = require('fs-extra')
|
||||
const ChildProcess = require('child_process')
|
||||
const ClsiApp = require('./helpers/ClsiApp')
|
||||
const logger = require('@overleaf/logger')
|
||||
|
@ -204,13 +203,13 @@ describe('Example Documents', function () {
|
|||
ClsiApp.ensureRunning(done)
|
||||
})
|
||||
before(function (done) {
|
||||
fsExtra.remove(fixturePath('tmp'), done)
|
||||
fs.rm(fixturePath('tmp'), { force: true, recursive: true }, done)
|
||||
})
|
||||
before(function (done) {
|
||||
fs.mkdir(fixturePath('tmp'), done)
|
||||
})
|
||||
after(function (done) {
|
||||
fsExtra.remove(fixturePath('tmp'), done)
|
||||
fs.rm(fixturePath('tmp'), { force: true, recursive: true }, done)
|
||||
})
|
||||
|
||||
return Array.from(fs.readdirSync(fixturePath('examples'))).map(exampleDir =>
|
||||
|
|
|
@ -116,14 +116,12 @@ describe('CompileManager', function () {
|
|||
lstat: sinon.stub(),
|
||||
stat: sinon.stub(),
|
||||
readFile: sinon.stub(),
|
||||
mkdir: sinon.stub().resolves(),
|
||||
}
|
||||
this.fsPromises.lstat.withArgs(this.compileDir).resolves(this.dirStats)
|
||||
this.fsPromises.stat
|
||||
.withArgs(Path.join(this.compileDir, 'output.synctex.gz'))
|
||||
.resolves(this.fileStats)
|
||||
this.fse = {
|
||||
ensureDir: sinon.stub().resolves(),
|
||||
}
|
||||
|
||||
this.CompileManager = SandboxedModule.require(MODULE_PATH, {
|
||||
requires: {
|
||||
|
@ -145,7 +143,6 @@ describe('CompileManager', function () {
|
|||
'./LockManager': this.LockManager,
|
||||
'./SynctexOutputParser': this.SynctexOutputParser,
|
||||
'fs/promises': this.fsPromises,
|
||||
'fs-extra': this.fse,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
@ -177,7 +174,9 @@ describe('CompileManager', function () {
|
|||
})
|
||||
|
||||
it('should ensure that the compile directory exists', function () {
|
||||
expect(this.fse.ensureDir).to.have.been.calledWith(this.compileDir)
|
||||
expect(this.fsPromises.mkdir).to.have.been.calledWith(this.compileDir, {
|
||||
recursive: true,
|
||||
})
|
||||
})
|
||||
|
||||
it('should not run LaTeX', function () {
|
||||
|
@ -193,7 +192,9 @@ describe('CompileManager', function () {
|
|||
})
|
||||
|
||||
it('should ensure that the compile directory exists', function () {
|
||||
expect(this.fse.ensureDir).to.have.been.calledWith(this.compileDir)
|
||||
expect(this.fsPromises.mkdir).to.have.been.calledWith(this.compileDir, {
|
||||
recursive: true,
|
||||
})
|
||||
})
|
||||
|
||||
it('should write the resources to disk', function () {
|
||||
|
|
|
@ -29,9 +29,9 @@ describe('UrlCache', function () {
|
|||
'@overleaf/settings': (this.Settings = {
|
||||
path: { clsiCacheDir: '/cache/dir' },
|
||||
}),
|
||||
'fs-extra': (this.fse = { remove: sinon.stub().resolves() }),
|
||||
fs: (this.fs = {
|
||||
promises: {
|
||||
rm: sinon.stub().resolves(),
|
||||
copyFile: sinon.stub().resolves(),
|
||||
},
|
||||
}),
|
||||
|
@ -105,7 +105,10 @@ describe('UrlCache', function () {
|
|||
|
||||
it('should clear the cache in bulk', function () {
|
||||
expect(
|
||||
this.fse.remove.calledWith('/cache/dir/' + this.project_id)
|
||||
this.fs.promises.rm.calledWith('/cache/dir/' + this.project_id, {
|
||||
force: true,
|
||||
recursive: true,
|
||||
})
|
||||
).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue