diff --git a/lib/spark.js b/lib/spark.js index 624a4dd..394dcdf 100644 --- a/lib/spark.js +++ b/lib/spark.js @@ -211,10 +211,17 @@ export default class Spark { this.handleRunError(err) } const duration = Date.now() - started - const baseDelay = APPROX_ROUND_LENGTH_IN_MS / this.#tasker.maxTasksPerRound - const delay = baseDelay - duration + const delay = calculateDelayBeforeNextTask({ + roundLengthInMs: APPROX_ROUND_LENGTH_IN_MS, + maxTasksPerRound: this.#tasker.maxTasksPerRound, + lastTaskDurationInMs: duration + }) + if (delay > 0) { - console.log('Sleeping for %s seconds before starting the next task...', Math.round(delay / 1000)) + console.log( + 'Sleeping for %s seconds before starting the next task...', + Math.round(delay / 1000) + ) await sleep(delay) console.log() // add an empty line to visually delimit logs from different tasks } @@ -231,6 +238,22 @@ export default class Spark { } } +/** + * @param {object} args + * @param {number} args.roundLengthInMs + * @param {number} args.maxTasksPerRound + * @param {number} args.lastTaskDurationInMs + */ +export function calculateDelayBeforeNextTask ({ + roundLengthInMs, + maxTasksPerRound, + lastTaskDurationInMs +}) { + const baseDelay = roundLengthInMs / maxTasksPerRound + const delay = baseDelay - lastTaskDurationInMs + return Math.min(delay, 60_000) +} + export function newStats () { return { timeout: false, diff --git a/test/spark.js b/test/spark.js index f73bc66..4dd4508 100644 --- a/test/spark.js +++ b/test/spark.js @@ -1,6 +1,6 @@ /* global Zinnia */ -import Spark, { newStats } from '../lib/spark.js' +import Spark, { calculateDelayBeforeNextTask, newStats } from '../lib/spark.js' import { test } from 'zinnia:test' import { assertInstanceOf, assertEquals, assertArrayIncludes } from 'zinnia:assert' import { SPARK_VERSION } from '../lib/constants.js' @@ -271,3 +271,33 @@ test('submitRetrieval', async () => { } ]) }) + +test('calculateDelayBeforeNextTask() returns value based on average task duration', () => { + const delay = calculateDelayBeforeNextTask({ + lastTaskDurationInMs: 3_000, + + // one task every 10 seconds (on average) + roundLengthInMs: 60_000, + maxTasksPerRound: 6 + }) + assertEquals(delay, 7_000) +}) + +test('calculateDelayBeforeNextTask() handles zero tasks per round', () => { + const delay = calculateDelayBeforeNextTask({ + maxTasksPerRound: 0, + // the values below are not important + roundLengthInMs: 12345, + lastTaskDurationInMs: 12 + }) + assertEquals(delay, 60_000) +}) + +test('calculateDelayBeforeNextTask() handles one task per round', () => { + const delay = calculateDelayBeforeNextTask({ + roundLengthInMs: 20 * 60_000, + maxTasksPerRound: 1, + lastTaskDurationInMs: 1_000 + }) + assertEquals(delay, 60_000) +})