Implement test to reduce compile timeout to 20 seconds (#14705)

Compile timeout reduction to 20s for treatment users

Co-authored-by: Rebeka <rebeka.dekany@overleaf.com>
GitOrigin-RevId: 54f70fe4b1fc631cef966deb0c1d28c904dd3a44
This commit is contained in:
Thomas
2023-09-19 08:03:52 +00:00
committed by Copybot
co-authored by Rebeka
parent d04a1d3767
commit 31cb9e336b
22 changed files with 838 additions and 8 deletions
@@ -114,6 +114,15 @@ module.exports = CompileController = {
stopOnFirstError,
}
// temporary override to force the new compile timeout
const forceNewCompileTimeout = req.query.force_new_compile_timeout
if (
forceNewCompileTimeout === 'active' ||
forceNewCompileTimeout === 'changing'
) {
options.forceNewCompileTimeout = forceNewCompileTimeout
}
if (req.body.rootDoc_id) {
options.rootDoc_id = req.body.rootDoc_id
} else if (
@@ -11,7 +11,11 @@ const { RateLimiter } = require('../../infrastructure/RateLimiter')
const SplitTestHandler = require('../SplitTests/SplitTestHandler')
const { getAnalyticsIdFromMongoUser } = require('../Analytics/AnalyticsHelper')
const NEW_COMPILE_TIMEOUT_ENFORCED_CUTOFF = new Date('2023-09-18T11:00:00.000Z')
module.exports = CompileManager = {
NEW_COMPILE_TIMEOUT_ENFORCED_CUTOFF,
compile(projectId, userId, options = {}, _callback) {
const timer = new Metrics.Timer('editor.compile')
const callback = function (...args) {
@@ -54,6 +58,16 @@ module.exports = CompileManager = {
const value = limits[key]
options[key] = value
}
if (options.timeout !== 20) {
// temporary override to force the new compile timeout
if (options.forceNewCompileTimeout === 'active') {
options.timeout = 20
} else if (
options.forceNewCompileTimeout === 'changing'
) {
options.timeout = 60
}
}
// Put a lower limit on autocompiles for free users, based on compileGroup
CompileManager._checkCompileGroupAutoCompileLimit(
options.isAutoCompile,
@@ -149,6 +163,7 @@ module.exports = CompileManager = {
betaProgram: 1,
features: 1,
splitTests: 1,
signUpDate: 1, // for compile-timeout-20s
},
function (err, owner) {
if (err) {
@@ -176,7 +191,28 @@ module.exports = CompileManager = {
limits.compileBackendClass = compileBackendClass
limits.showFasterCompilesFeedbackUI =
showFasterCompilesFeedbackUI
callback(null, limits)
if (compileBackendClass === 'n2d' && limits.timeout <= 60) {
// project owners with faster compiles but with <= 60 compile timeout (default)
// will have a 20s compile timeout
// The compile-timeout-20s split test exists to enable a gradual rollout
SplitTestHandler.getAssignmentForMongoUser(
owner,
'compile-timeout-20s',
(err, assignment) => {
if (err) return callback(err)
if (assignment?.variant === '20s') {
if (
owner.signUpDate > NEW_COMPILE_TIMEOUT_ENFORCED_CUTOFF
) {
limits.timeout = 20
}
}
callback(null, limits)
}
)
} else {
callback(null, limits)
}
}
)
}
@@ -14,6 +14,10 @@ const Errors = require('../Errors/Errors')
const DocstoreManager = require('../Docstore/DocstoreManager')
const logger = require('@overleaf/logger')
const { expressify } = require('../../util/promises')
const SplitTestHandler = require('../SplitTests/SplitTestHandler')
const {
NEW_COMPILE_TIMEOUT_ENFORCED_CUTOFF,
} = require('../Compile/CompileManager')
module.exports = {
joinProject: expressify(joinProject),
@@ -67,6 +71,30 @@ async function joinProject(req, res, next) {
if (!project) {
return res.sendStatus(403)
}
// Compile timeout 20s test
if (project.features?.compileTimeout <= 60) {
const compileAssignment =
await SplitTestHandler.promises.getAssignmentForMongoUser(
project.owner._id,
'compile-backend-class-n2d'
)
if (compileAssignment?.variant === 'n2d') {
const timeoutAssignment =
await SplitTestHandler.promises.getAssignmentForMongoUser(
project.owner._id,
'compile-timeout-20s'
)
if (timeoutAssignment?.variant === '20s') {
if (project.owner.signUpDate > NEW_COMPILE_TIMEOUT_ENFORCED_CUTOFF) {
// New users will see a 10s warning and compile fail at 20s
project.showNewCompileTimeoutUI = 'active'
} else {
// Older users aren't limited to 20s, but will see a notice of upcoming changes if compile >20s
project.showNewCompileTimeoutUI = 'changing'
}
}
}
}
// Hide sensitive data if the user is restricted
if (isRestrictedUser) {
project.owner = { _id: project.owner._id }