Merge pull request #24269 from overleaf/bg-backup-replication-smoothing

extend backup scheduler to delay jobs for load levelling

GitOrigin-RevId: be62c458d3be464bf80ca590fcc107c2760aa061
This commit is contained in:
Brian Gough
2025-03-13 09:06:28 +00:00
committed by Copybot
parent a178c0f400
commit 2d48c86e61
@@ -46,6 +46,12 @@ const optionDefinitions = [
type: Number, type: Number,
description: 'Limit the number of jobs to be added', description: 'Limit the number of jobs to be added',
}, },
{
name: 'interval',
type: Number,
description: 'Time in seconds to spread jobs over (default: 300)',
defaultValue: 300,
},
{ {
name: 'backoff-delay', name: 'backoff-delay',
type: Number, type: Number,
@@ -190,6 +196,7 @@ async function processPendingProjects(
showOnly, showOnly,
limit, limit,
verbose, verbose,
jobInterval,
jobOpts = {} jobOpts = {}
) { ) {
const timeIntervalMs = age * 1000 const timeIntervalMs = age * 1000
@@ -212,10 +219,11 @@ async function processPendingProjects(
`Project: ${projectId} (pending since: ${formatPendingTime(pendingAt)})` `Project: ${projectId} (pending since: ${formatPendingTime(pendingAt)})`
) )
} else if (!showOnly) { } else if (!showOnly) {
const delay = Math.floor(Math.random() * jobInterval * 1000) // add random delay to avoid all jobs running simultaneously
const { job, added } = await addJobWithCheck( const { job, added } = await addJobWithCheck(
backupQueue, backupQueue,
{ projectId, pendingChangeAt: pendingAt.getTime() }, { projectId, pendingChangeAt: pendingAt.getTime() },
{ ...jobOpts, jobId: projectId } { ...jobOpts, delay, jobId: projectId }
) )
if (added) { if (added) {
@@ -304,13 +312,20 @@ async function run() {
setupMonitoring() setupMonitoring()
} else if (options['queue-pending'] !== undefined) { } else if (options['queue-pending'] !== undefined) {
const age = validatePendingTime('queue-pending', options['queue-pending']) const age = validatePendingTime('queue-pending', options['queue-pending'])
await processPendingProjects(age, false, options.limit, options.verbose, { await processPendingProjects(
attempts: options.attempts, age,
backoff: { false,
type: 'exponential', options.limit,
delay: options['backoff-delay'], options.verbose,
}, options.interval,
}) {
attempts: options.attempts,
backoff: {
type: 'exponential',
delay: options['backoff-delay'],
},
}
)
} else if (options['show-pending'] !== undefined) { } else if (options['show-pending'] !== undefined) {
const age = validatePendingTime('show-pending', options['show-pending']) const age = validatePendingTime('show-pending', options['show-pending'])
await processPendingProjects(age, true, options.limit, options.verbose) await processPendingProjects(age, true, options.limit, options.verbose)
@@ -330,6 +345,9 @@ async function run() {
' --show-pending TIME Show count of pending projects older than TIME seconds' ' --show-pending TIME Show count of pending projects older than TIME seconds'
) )
console.log(' --limit N Limit the number of jobs to be added') console.log(' --limit N Limit the number of jobs to be added')
console.log(
' --interval TIME Time interval in seconds to spread jobs over'
)
console.log( console.log(
' --backoff-delay TIME Backoff delay in milliseconds for failed jobs (default: 1000)' ' --backoff-delay TIME Backoff delay in milliseconds for failed jobs (default: 1000)'
) )