Merge pull request #19793 from wss-ycabrera/PBI_900245_task_worker_fix

Fix bug 19792:  Backstage does not immediately apply new schedules for scheduled items
This commit is contained in:
Fredrik Adelöw
2023-09-14 13:38:14 +02:00
committed by GitHub
3 changed files with 74 additions and 2 deletions
+8
View File
@@ -0,0 +1,8 @@
---
'@backstage/backend-tasks': patch
---
When starting a task that existed before, with a faster schedule than it
previously had, the task will now correctly obey the faster schedule
immediately. Before this fix, the new schedule was only obeyed after the next
pending (according to the old schedule) run had completed.
@@ -330,6 +330,48 @@ describe('TaskWorker', () => {
const before = fn1.mock.calls.length;
await promise2;
expect(fn1.mock.calls.length).toBeGreaterThan(before);
await knex.destroy();
},
);
it.each(databases.eachSupportedId())(
'next_run_start_at is always the min between schedule changes, %p',
async databaseId => {
const knex = await databases.init(databaseId);
await migrateBackendTasks(knex);
const fn = jest.fn(
async () => new Promise<void>(resolve => setTimeout(resolve, 50)),
);
const settings: TaskSettingsV2 = {
version: 2,
cadence: '*/15 * * * *',
initialDelayDuration: 'PT2M',
timeoutAfterDuration: 'PT1M',
};
const worker = new TaskWorker('task99', fn, knex, logger);
await worker.persistTask(settings);
const row1 = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0];
const settings2 = {
...settings,
cadence: '*/2 * * * *',
initialDelayDuration: 'PT1M',
};
await worker.persistTask(settings2);
const row2 = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0];
expect(row2.next_run_start_at).not.toStrictEqual(row1.next_run_start_at);
const settings3 = { ...settings };
await worker.persistTask(settings3);
const row3 = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0];
expect(row3.next_run_start_at).toStrictEqual(row2.next_run_start_at);
await knex.destroy();
},
);
});
+24 -2
View File
@@ -192,14 +192,36 @@ export class TaskWorker {
// It's OK if the task already exists; if it does, just replace its
// settings with the new value and start the loop as usual.
const settingsJson = JSON.stringify(settings);
await this.knex<DbTasksRow>(DB_TASKS_TABLE)
.insert({
id: this.taskId,
settings_json: JSON.stringify(settings),
settings_json: settingsJson,
next_run_start_at: startAt,
})
.onConflict('id')
.merge(['settings_json']);
.merge(
this.knex.client.config.client.includes('mysql')
? {
settings_json: settingsJson,
next_run_start_at: this.knex.raw(
`CASE WHEN ?? < ?? THEN ?? ELSE ?? END`,
[startAt, 'next_run_start_at', startAt, 'next_run_start_at'],
),
}
: {
settings_json: this.knex.ref('excluded.settings_json'),
next_run_start_at: this.knex.raw(
`CASE WHEN ?? < ?? THEN ?? ELSE ?? END`,
[
'excluded.next_run_start_at',
`${DB_TASKS_TABLE}.next_run_start_at`,
'excluded.next_run_start_at',
`${DB_TASKS_TABLE}.next_run_start_at`,
],
),
},
);
}
/**