feat: add functionality to get scheduled tasks

add new functionality to PluginTaskScheduler to return local and global
tasks. this is to be able to trigger those tasks manually using the
triggerTask functionality when there's no clear way to figure out the
correct id to use as they in many cases come from a plugin.

this is also usable for the upcoming debug plugin, see #9737

Signed-off-by: Heikki Hellgren <heikki.hellgren@op.fi>
This commit is contained in:
Heikki Hellgren
2023-02-22 12:46:22 +02:00
parent 9c61bdaf40
commit 1578276708
6 changed files with 81 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-tasks': minor
---
add functionality to get descriptions from the scheduler for triggering
+5
View File
@@ -16,6 +16,7 @@ export type HumanDuration = HumanDuration_2;
// @public
export interface PluginTaskScheduler {
createScheduledTaskRunner(schedule: TaskScheduleDefinition): TaskRunner;
getScheduledTasks(): TaskDescriptor[];
scheduleTask(
task: TaskScheduleDefinition & TaskInvocationDefinition,
): Promise<void>;
@@ -27,6 +28,10 @@ export function readTaskScheduleDefinitionFromConfig(
config: Config,
): TaskScheduleDefinition;
// @public
export type TaskDescriptor = TaskScheduleDefinition &
Exclude<TaskInvocationDefinition, 'fn' | 'signal'>;
// @public
export type TaskFunction =
| ((abortSignal: AbortSignal) => void | Promise<void>)
@@ -304,6 +304,47 @@ describe('PluginTaskManagerImpl', () => {
);
});
describe('can fetch task ids', () => {
it.each(databases.eachSupportedId())(
'can fetch both global and local task ids, %p',
async databaseId => {
const { manager } = await init(databaseId);
const fn = jest.fn();
const promise = new Promise(resolve => fn.mockImplementation(resolve));
await manager.scheduleTask({
id: 'task1',
timeout: Duration.fromMillis(5000),
frequency: Duration.fromMillis(5000),
fn,
scope: 'global',
});
await manager.scheduleTask({
id: 'task2',
timeout: Duration.fromMillis(5000),
frequency: Duration.fromMillis(5000),
fn,
scope: 'local',
});
await promise;
const tasks = manager.getScheduledTasks();
expect(tasks.length).toEqual(2);
expect(tasks[0].id).toEqual('task1');
expect(tasks[1].id).toEqual('task2');
expect(tasks[0].scope).toEqual('global');
expect(tasks[1].scope).toEqual('local');
expect(tasks[0].fn).toBeUndefined();
expect(tasks[1].fn).toBeUndefined();
expect(tasks[0].signal).toBeUndefined();
expect(tasks[1].signal).toBeUndefined();
},
60_000,
);
});
describe('parseDuration', () => {
it('should parse durations', () => {
expect(parseDuration({ milliseconds: 5000 })).toEqual('PT5S');
@@ -21,6 +21,7 @@ import { LocalTaskWorker } from './LocalTaskWorker';
import { TaskWorker } from './TaskWorker';
import {
PluginTaskScheduler,
TaskDescriptor,
TaskInvocationDefinition,
TaskRunner,
TaskScheduleDefinition,
@@ -32,6 +33,7 @@ import { validateId } from './util';
*/
export class PluginTaskSchedulerImpl implements PluginTaskScheduler {
private readonly localTasksById = new Map<string, LocalTaskWorker>();
private readonly allScheduledTasks: TaskDescriptor[] = [];
constructor(
private readonly databaseFactory: () => Promise<Knex>,
@@ -94,6 +96,8 @@ export class PluginTaskSchedulerImpl implements PluginTaskScheduler {
this.localTasksById.set(task.id, worker);
}
const { fn: _, signal: __, ...descriptor } = task;
this.allScheduledTasks.push(descriptor as TaskDescriptor);
}
createScheduledTaskRunner(schedule: TaskScheduleDefinition): TaskRunner {
@@ -103,6 +107,10 @@ export class PluginTaskSchedulerImpl implements PluginTaskScheduler {
},
};
}
getScheduledTasks(): TaskDescriptor[] {
return this.allScheduledTasks;
}
}
export function parseDuration(
@@ -19,6 +19,7 @@ export { TaskScheduler } from './TaskScheduler';
export type {
PluginTaskScheduler,
TaskFunction,
TaskDescriptor,
TaskInvocationDefinition,
TaskRunner,
TaskScheduleDefinition,
+21
View File
@@ -31,6 +31,14 @@ export type TaskFunction =
| ((abortSignal: AbortSignal) => void | Promise<void>)
| (() => void | Promise<void>);
/**
* A type to describe a scheduled task.
*
* @public
*/
export type TaskDescriptor = TaskScheduleDefinition &
Exclude<TaskInvocationDefinition, 'fn' | 'signal'>;
/**
* Options that control the scheduling of a task.
*
@@ -307,6 +315,19 @@ export interface PluginTaskScheduler {
* @param schedule - The task schedule
*/
createScheduledTaskRunner(schedule: TaskScheduleDefinition): TaskRunner;
/**
* Returns all scheduled tasks registered to this scheduler.
*
* @remarks
*
* This method is useful for triggering tasks manually using the triggerTask
* functionality. Note that the returned tasks contain only tasks that have
* been initialized in this instance of the scheduler.
*
* @returns Scheduled tasks
*/
getScheduledTasks(): TaskDescriptor[];
}
function isValidOptionalDurationString(d: string | undefined): boolean {