feat(task): add task labels and push-based task events
This commit is contained in:
@@ -2,7 +2,7 @@ import * as plugins from './taskbuffer.plugins.js';
|
||||
import { BufferRunner } from './taskbuffer.classes.bufferrunner.js';
|
||||
import { CycleCounter } from './taskbuffer.classes.cyclecounter.js';
|
||||
import { TaskStep, type ITaskStep } from './taskbuffer.classes.taskstep.js';
|
||||
import type { ITaskMetadata } from './taskbuffer.interfaces.js';
|
||||
import type { ITaskMetadata, ITaskEvent, TTaskEventType } from './taskbuffer.interfaces.js';
|
||||
|
||||
import { logger } from './taskbuffer.logging.js';
|
||||
|
||||
@@ -91,6 +91,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
||||
// Reset steps and error state at the beginning of task execution
|
||||
taskToRun.resetSteps();
|
||||
taskToRun.lastError = undefined;
|
||||
taskToRun.emitEvent('started');
|
||||
|
||||
done.promise
|
||||
.then(async () => {
|
||||
@@ -98,6 +99,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
||||
|
||||
// Complete all steps when task finishes
|
||||
taskToRun.completeAllSteps();
|
||||
taskToRun.emitEvent(taskToRun.lastError ? 'failed' : 'completed');
|
||||
|
||||
// When the task has finished running, resolve the finished promise
|
||||
taskToRun.resolveFinished();
|
||||
@@ -109,6 +111,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
||||
})
|
||||
.catch((err) => {
|
||||
taskToRun.running = false;
|
||||
taskToRun.emitEvent('failed', { error: err instanceof Error ? err.message : String(err) });
|
||||
|
||||
// Resolve finished so blocking dependants don't hang
|
||||
taskToRun.resolveFinished();
|
||||
@@ -218,6 +221,8 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
||||
public catchErrors: boolean = false;
|
||||
public lastError?: Error;
|
||||
public errorCount: number = 0;
|
||||
public labels: Record<string, string> = {};
|
||||
public readonly eventSubject = new plugins.smartrx.rxjs.Subject<ITaskEvent>();
|
||||
|
||||
public get idle() {
|
||||
return !this.running;
|
||||
@@ -227,6 +232,38 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
||||
this.lastError = undefined;
|
||||
}
|
||||
|
||||
public setLabel(key: string, value: string): void {
|
||||
this.labels[key] = value;
|
||||
}
|
||||
|
||||
public getLabel(key: string): string | undefined {
|
||||
return this.labels[key];
|
||||
}
|
||||
|
||||
public removeLabel(key: string): boolean {
|
||||
if (key in this.labels) {
|
||||
delete this.labels[key];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public hasLabel(key: string, value?: string): boolean {
|
||||
if (value !== undefined) {
|
||||
return this.labels[key] === value;
|
||||
}
|
||||
return key in this.labels;
|
||||
}
|
||||
|
||||
private emitEvent(type: TTaskEventType, extra?: Partial<ITaskEvent>): void {
|
||||
this.eventSubject.next({
|
||||
type,
|
||||
task: this.getMetadata(),
|
||||
timestamp: Date.now(),
|
||||
...extra,
|
||||
});
|
||||
}
|
||||
|
||||
public taskSetup: ITaskSetupFunction<T>;
|
||||
public setupValue: T;
|
||||
|
||||
@@ -247,6 +284,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
||||
taskSetup?: ITaskSetupFunction<T>;
|
||||
steps?: TSteps;
|
||||
catchErrors?: boolean;
|
||||
labels?: Record<string, string>;
|
||||
}) {
|
||||
this.taskFunction = optionsArg.taskFunction;
|
||||
this.preTask = optionsArg.preTask;
|
||||
@@ -257,6 +295,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
||||
this.name = optionsArg.name;
|
||||
this.taskSetup = optionsArg.taskSetup;
|
||||
this.catchErrors = optionsArg.catchErrors ?? false;
|
||||
this.labels = optionsArg.labels ? { ...optionsArg.labels } : {};
|
||||
|
||||
// Initialize steps if provided
|
||||
if (optionsArg.steps) {
|
||||
@@ -309,8 +348,8 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
||||
if (step) {
|
||||
step.start();
|
||||
this.currentStepName = stepName as string;
|
||||
|
||||
// Emit event for frontend updates (could be enhanced with event emitter)
|
||||
this.emitEvent('step', { stepName: stepName as string });
|
||||
|
||||
if (this.name) {
|
||||
logger.log('info', `Task ${this.name}: Starting step "${stepName}" - ${step.description}`);
|
||||
}
|
||||
@@ -369,6 +408,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
||||
cronSchedule: this.cronJob?.cronExpression,
|
||||
lastError: this.lastError?.message,
|
||||
errorCount: this.errorCount,
|
||||
labels: { ...this.labels },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user