2022-03-25 11:14:49 +00:00
|
|
|
import * as plugins from './taskbuffer.plugins.js';
|
|
|
|
import { Task } from './taskbuffer.classes.task.js';
|
2023-08-12 10:24:10 +00:00
|
|
|
import { AbstractDistributedCoordinator, type IDistributedTaskRequestResult } from './taskbuffer.classes.distributedcoordinator.js';
|
2017-06-17 14:56:33 +00:00
|
|
|
|
2019-09-08 20:45:36 +00:00
|
|
|
export interface ICronJob {
|
|
|
|
cronString: string;
|
2023-08-12 10:24:10 +00:00
|
|
|
taskName: string;
|
2019-09-08 20:45:36 +00:00
|
|
|
job: any;
|
|
|
|
}
|
2017-06-17 14:56:33 +00:00
|
|
|
|
2022-11-14 13:54:26 +00:00
|
|
|
export interface ITaskManagerConstructorOptions {
|
2023-07-26 12:16:33 +00:00
|
|
|
distributedCoordinator?: AbstractDistributedCoordinator;
|
2022-11-14 13:54:26 +00:00
|
|
|
}
|
|
|
|
|
2017-06-17 14:56:33 +00:00
|
|
|
export class TaskManager {
|
2023-01-07 18:05:29 +00:00
|
|
|
public randomId = plugins.isounique.uni();
|
2020-07-12 00:48:51 +00:00
|
|
|
public taskMap = new plugins.lik.ObjectMap<Task>();
|
|
|
|
private cronJobManager = new plugins.smarttime.CronManager();
|
2022-11-14 13:54:26 +00:00
|
|
|
public options: ITaskManagerConstructorOptions = {
|
2023-07-26 12:16:33 +00:00
|
|
|
distributedCoordinator: null,
|
2022-11-14 13:54:26 +00:00
|
|
|
};
|
|
|
|
|
2023-08-12 10:24:10 +00:00
|
|
|
constructor(options: ITaskManagerConstructorOptions = {}) {
|
|
|
|
this.options = Object.assign(this.options, options);
|
2017-06-17 14:56:33 +00:00
|
|
|
}
|
|
|
|
|
2023-08-12 10:24:10 +00:00
|
|
|
public getTaskByName(taskName: string): Task {
|
|
|
|
return this.taskMap.findSync((task) => task.name === taskName);
|
2017-06-17 14:56:33 +00:00
|
|
|
}
|
|
|
|
|
2023-08-12 10:24:10 +00:00
|
|
|
public addTask(task: Task): void {
|
|
|
|
if (!task.name) {
|
|
|
|
throw new Error('Task must have a name to be added to taskManager');
|
2017-06-17 14:56:33 +00:00
|
|
|
}
|
2023-08-12 10:24:10 +00:00
|
|
|
this.taskMap.add(task);
|
2017-06-17 14:56:33 +00:00
|
|
|
}
|
|
|
|
|
2023-08-12 10:24:10 +00:00
|
|
|
public addAndScheduleTask(task: Task, cronString: string) {
|
|
|
|
this.addTask(task);
|
|
|
|
this.scheduleTaskByName(task.name, cronString);
|
2017-06-17 14:56:33 +00:00
|
|
|
}
|
|
|
|
|
2023-08-12 10:24:10 +00:00
|
|
|
public async triggerTaskByName(taskName: string): Promise<any> {
|
|
|
|
const taskToTrigger = this.getTaskByName(taskName);
|
2017-06-17 14:56:33 +00:00
|
|
|
if (!taskToTrigger) {
|
2023-08-12 10:24:10 +00:00
|
|
|
throw new Error(`No task with the name ${taskName} found.`);
|
2017-06-17 14:56:33 +00:00
|
|
|
}
|
2018-08-04 15:53:22 +00:00
|
|
|
return taskToTrigger.trigger();
|
2017-06-17 14:56:33 +00:00
|
|
|
}
|
|
|
|
|
2019-09-08 20:45:36 +00:00
|
|
|
public async triggerTask(task: Task) {
|
|
|
|
return task.trigger();
|
|
|
|
}
|
|
|
|
|
2023-08-12 10:24:10 +00:00
|
|
|
public scheduleTaskByName(taskName: string, cronString: string) {
|
|
|
|
const taskToSchedule = this.getTaskByName(taskName);
|
|
|
|
if (!taskToSchedule) {
|
|
|
|
throw new Error(`No task with the name ${taskName} found.`);
|
|
|
|
}
|
|
|
|
this.handleTaskScheduling(taskToSchedule, cronString);
|
|
|
|
}
|
|
|
|
|
|
|
|
private handleTaskScheduling(task: Task, cronString: string) {
|
2023-07-26 12:16:33 +00:00
|
|
|
const cronJob = this.cronJobManager.addCronjob(
|
2023-08-12 10:24:10 +00:00
|
|
|
cronString,
|
|
|
|
async (triggerTime: number) => {
|
|
|
|
this.logTaskState(task);
|
2023-07-26 12:16:33 +00:00
|
|
|
if (this.options.distributedCoordinator) {
|
2023-08-12 10:24:10 +00:00
|
|
|
const announcementResult = await this.performDistributedConsultation(task, triggerTime);
|
2023-07-26 12:16:33 +00:00
|
|
|
if (!announcementResult.shouldTrigger) {
|
2023-08-12 10:24:10 +00:00
|
|
|
console.log('Distributed coordinator result: NOT EXECUTING');
|
2023-07-26 12:16:33 +00:00
|
|
|
return;
|
|
|
|
} else {
|
2023-08-12 10:24:10 +00:00
|
|
|
console.log('Distributed coordinator result: CHOSEN AND EXECUTING');
|
2023-07-26 12:16:33 +00:00
|
|
|
}
|
2023-01-07 18:05:29 +00:00
|
|
|
}
|
2023-08-12 10:24:10 +00:00
|
|
|
await task.trigger();
|
2022-11-14 13:54:26 +00:00
|
|
|
}
|
2023-07-26 12:16:33 +00:00
|
|
|
);
|
2023-08-12 10:24:10 +00:00
|
|
|
task.cronJob = cronJob;
|
2017-06-17 14:56:33 +00:00
|
|
|
}
|
|
|
|
|
2023-08-12 10:24:10 +00:00
|
|
|
private logTaskState(task: Task) {
|
|
|
|
console.log(`Taskbuffer schedule triggered task >>${task.name}<<`);
|
|
|
|
const bufferState = task.buffered
|
|
|
|
? `buffered with max ${task.bufferMax} buffered calls`
|
|
|
|
: `unbuffered`;
|
|
|
|
console.log(`Task >>${task.name}<< is ${bufferState}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
private async performDistributedConsultation(task: Task, triggerTime: number): Promise<IDistributedTaskRequestResult> {
|
|
|
|
console.log('Found a distributed coordinator, performing consultation.');
|
|
|
|
return this.options.distributedCoordinator.fireDistributedTaskRequest({
|
|
|
|
submitterId: this.randomId,
|
|
|
|
status: 'requesting',
|
|
|
|
taskExecutionParallel: 1,
|
|
|
|
taskExecutionTime: triggerTime,
|
|
|
|
taskExecutionTimeout: task.timeout,
|
|
|
|
taskName: task.name,
|
|
|
|
taskVersion: task.version,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public descheduleTaskByName(taskName: string) {
|
|
|
|
const task = this.getTaskByName(taskName);
|
|
|
|
if (task && task.cronJob) {
|
|
|
|
this.cronJobManager.removeCronjob(task.cronJob);
|
|
|
|
task.cronJob = null;
|
2020-07-12 00:48:51 +00:00
|
|
|
}
|
|
|
|
if (this.cronJobManager.cronjobs.isEmpty) {
|
|
|
|
this.cronJobManager.stop();
|
|
|
|
}
|
2017-06-18 11:25:09 +00:00
|
|
|
}
|
2019-09-08 20:45:36 +00:00
|
|
|
|
|
|
|
public async descheduleTask(task: Task) {
|
|
|
|
await this.descheduleTaskByName(task.name);
|
|
|
|
}
|
2023-08-04 09:58:53 +00:00
|
|
|
|
2023-08-12 10:24:10 +00:00
|
|
|
public getScheduleForTaskName(taskName: string): string | null {
|
|
|
|
const task = this.getTaskByName(taskName);
|
|
|
|
return task && task.cronJob ? task.cronJob.cronExpression : null;
|
2023-08-04 09:58:53 +00:00
|
|
|
}
|
2020-09-02 13:04:12 +00:00
|
|
|
|
|
|
|
public start() {
|
|
|
|
this.cronJobManager.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
public stop() {
|
|
|
|
this.cronJobManager.stop();
|
|
|
|
}
|
2017-06-17 14:56:33 +00:00
|
|
|
}
|