Merge pull request #155 from overleaf/ho-limit-lifespan

limit clsi lifespan via health checks and PROCESS_LIFE_SPAN_LIMIT_MS
This commit is contained in:
Henry Oswald
2020-04-23 13:51:09 +01:00
committed by GitHub
2 changed files with 36 additions and 35 deletions

58
app.js
View File

@@ -22,7 +22,6 @@ const ContentTypeMapper = require('./app/js/ContentTypeMapper')
const Errors = require('./app/js/Errors') const Errors = require('./app/js/Errors')
const Path = require('path') const Path = require('path')
const fs = require('fs')
Metrics.open_sockets.monitor(logger) Metrics.open_sockets.monitor(logger)
Metrics.memory.monitor(logger) Metrics.memory.monitor(logger)
@@ -208,23 +207,41 @@ const resCacher = {
setContentType: 'application/json' setContentType: 'application/json'
} }
let shutdownTime
if (Settings.processLifespanLimitMs) {
Settings.processLifespanLimitMs +=
Settings.processLifespanLimitMs * (Math.random() / 10)
shutdownTime = Date.now() + Settings.processLifespanLimitMs
logger.info('Lifespan limited to ', shutdownTime)
}
const checkIfProcessIsTooOld = function(cont) {
if (shutdownTime && shutdownTime < Date.now()) {
logger.log('shutting down, process is too old')
resCacher.send = function() {}
resCacher.code = 500
resCacher.body = { processToOld: true }
} else {
cont()
}
}
if (Settings.smokeTest) { if (Settings.smokeTest) {
let runSmokeTest const runSmokeTest = function() {
;(runSmokeTest = function() { checkIfProcessIsTooOld(function() {
logger.log('running smoke tests') logger.log('running smoke tests')
smokeTest.run(require.resolve(__dirname + '/test/smoke/js/SmokeTests.js'))( smokeTest.run(
{}, require.resolve(__dirname + '/test/smoke/js/SmokeTests.js')
resCacher )({}, resCacher)
)
return setTimeout(runSmokeTest, 30 * 1000) return setTimeout(runSmokeTest, 30 * 1000)
})() })
}
runSmokeTest()
} }
app.get('/health_check', function(req, res) { app.get('/health_check', function(req, res) {
res.contentType(resCacher != null ? resCacher.setContentType : undefined) res.contentType(resCacher.setContentType)
return res return res.status(resCacher.code).send(resCacher.body)
.status(resCacher != null ? resCacher.code : undefined)
.send(resCacher != null ? resCacher.body : undefined)
}) })
app.get('/smoke_test_force', (req, res) => app.get('/smoke_test_force', (req, res) =>
@@ -234,23 +251,6 @@ app.get('/smoke_test_force', (req, res) =>
) )
) )
const profiler = require('v8-profiler-node8')
app.get('/profile', function(req, res) {
const time = parseInt(req.query.time || '1000')
profiler.startProfiling('test')
return setTimeout(function() {
const profile = profiler.stopProfiling('test')
return res.json(profile)
}, time)
})
app.get('/heapdump', (req, res) =>
require('heapdump').writeSnapshot(
`/tmp/${Date.now()}.clsi.heapsnapshot`,
(err, filename) => res.send(filename)
)
)
app.use(function(error, req, res, next) { app.use(function(error, req, res, next) {
if (error instanceof Errors.NotFoundError) { if (error instanceof Errors.NotFoundError) {
logger.warn({ err: error, url: req.url }, 'not found error') logger.warn({ err: error, url: req.url }, 'not found error')

View File

@@ -22,6 +22,9 @@ module.exports = {
compileSizeLimit: process.env.COMPILE_SIZE_LIMIT || '7mb', compileSizeLimit: process.env.COMPILE_SIZE_LIMIT || '7mb',
processLifespanLimitMs:
parseInt(process.env.PROCESS_LIFE_SPAN_LIMIT_MS) || 60 * 60 * 24 * 1000 * 2,
path: { path: {
compilesDir: Path.resolve(__dirname + '/../compiles'), compilesDir: Path.resolve(__dirname + '/../compiles'),
clsiCacheDir: Path.resolve(__dirname + '/../cache'), clsiCacheDir: Path.resolve(__dirname + '/../cache'),
@@ -65,8 +68,7 @@ if (process.env.DOCKER_RUNNER) {
dockerRunner: process.env.DOCKER_RUNNER === 'true', dockerRunner: process.env.DOCKER_RUNNER === 'true',
docker: { docker: {
image: image:
process.env.TEXLIVE_IMAGE || process.env.TEXLIVE_IMAGE || 'quay.io/sharelatex/texlive-full:2017.1',
'quay.io/sharelatex/texlive-full:2017.1',
env: { env: {
HOME: '/tmp' HOME: '/tmp'
}, },
@@ -93,8 +95,7 @@ if (process.env.DOCKER_RUNNER) {
module.exports.path.synctexBaseDir = () => '/compile' module.exports.path.synctexBaseDir = () => '/compile'
module.exports.path.sandboxedCompilesHostDir = module.exports.path.sandboxedCompilesHostDir = process.env.COMPILES_HOST_DIR
process.env.COMPILES_HOST_DIR
module.exports.path.synctexBinHostPath = process.env.SYNCTEX_BIN_HOST_PATH module.exports.path.synctexBinHostPath = process.env.SYNCTEX_BIN_HOST_PATH
} }