@push.rocks/taskbuffer 4.0.0 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.d.ts +1 -1
- package/dist_ts/taskbuffer.classes.task.d.ts +9 -1
- package/dist_ts/taskbuffer.classes.task.js +36 -2
- package/dist_ts/taskbuffer.classes.taskmanager.d.ts +6 -1
- package/dist_ts/taskbuffer.classes.taskmanager.js +27 -3
- package/dist_ts/taskbuffer.interfaces.d.ts +9 -0
- package/dist_ts_web/ts/index.d.ts +1 -1
- package/dist_ts_web/ts/taskbuffer.classes.task.d.ts +9 -1
- package/dist_ts_web/ts/taskbuffer.classes.task.js +36 -2
- package/dist_ts_web/ts/taskbuffer.classes.taskmanager.d.ts +6 -1
- package/dist_ts_web/ts/taskbuffer.classes.taskmanager.js +27 -3
- package/dist_ts_web/ts/taskbuffer.interfaces.d.ts +9 -0
- package/dist_ts_web/ts_web/00_commitinfo_data.js +1 -1
- package/package.json +1 -1
- package/readme.hints.md +14 -0
- package/readme.md +538 -408
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +1 -1
- package/ts/taskbuffer.classes.task.ts +43 -3
- package/ts/taskbuffer.classes.taskmanager.ts +30 -3
- package/ts/taskbuffer.interfaces.ts +11 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/taskbuffer',
|
|
6
|
-
version: '4.
|
|
6
|
+
version: '4.1.1',
|
|
7
7
|
description: 'A flexible task management library supporting TypeScript, allowing for task buffering, scheduling, and execution with dependency management.'
|
|
8
8
|
}
|
package/ts/index.ts
CHANGED
|
@@ -12,7 +12,7 @@ export { TaskStep } from './taskbuffer.classes.taskstep.js';
|
|
|
12
12
|
export type { ITaskStep } from './taskbuffer.classes.taskstep.js';
|
|
13
13
|
|
|
14
14
|
// Metadata interfaces
|
|
15
|
-
export type { ITaskMetadata, ITaskExecutionReport, IScheduledTaskInfo } from './taskbuffer.interfaces.js';
|
|
15
|
+
export type { ITaskMetadata, ITaskExecutionReport, IScheduledTaskInfo, ITaskEvent, TTaskEventType } from './taskbuffer.interfaces.js';
|
|
16
16
|
|
|
17
17
|
import * as distributedCoordination from './taskbuffer.classes.distributedcoordinator.js';
|
|
18
18
|
export { distributedCoordination };
|
|
@@ -2,7 +2,7 @@ import * as plugins from './taskbuffer.plugins.js';
|
|
|
2
2
|
import { BufferRunner } from './taskbuffer.classes.bufferrunner.js';
|
|
3
3
|
import { CycleCounter } from './taskbuffer.classes.cyclecounter.js';
|
|
4
4
|
import { TaskStep, type ITaskStep } from './taskbuffer.classes.taskstep.js';
|
|
5
|
-
import type { ITaskMetadata } from './taskbuffer.interfaces.js';
|
|
5
|
+
import type { ITaskMetadata, ITaskEvent, TTaskEventType } from './taskbuffer.interfaces.js';
|
|
6
6
|
|
|
7
7
|
import { logger } from './taskbuffer.logging.js';
|
|
8
8
|
|
|
@@ -91,6 +91,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
91
91
|
// Reset steps and error state at the beginning of task execution
|
|
92
92
|
taskToRun.resetSteps();
|
|
93
93
|
taskToRun.lastError = undefined;
|
|
94
|
+
taskToRun.emitEvent('started');
|
|
94
95
|
|
|
95
96
|
done.promise
|
|
96
97
|
.then(async () => {
|
|
@@ -98,6 +99,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
98
99
|
|
|
99
100
|
// Complete all steps when task finishes
|
|
100
101
|
taskToRun.completeAllSteps();
|
|
102
|
+
taskToRun.emitEvent(taskToRun.lastError ? 'failed' : 'completed');
|
|
101
103
|
|
|
102
104
|
// When the task has finished running, resolve the finished promise
|
|
103
105
|
taskToRun.resolveFinished();
|
|
@@ -109,6 +111,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
109
111
|
})
|
|
110
112
|
.catch((err) => {
|
|
111
113
|
taskToRun.running = false;
|
|
114
|
+
taskToRun.emitEvent('failed', { error: err instanceof Error ? err.message : String(err) });
|
|
112
115
|
|
|
113
116
|
// Resolve finished so blocking dependants don't hang
|
|
114
117
|
taskToRun.resolveFinished();
|
|
@@ -218,6 +221,8 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
218
221
|
public catchErrors: boolean = false;
|
|
219
222
|
public lastError?: Error;
|
|
220
223
|
public errorCount: number = 0;
|
|
224
|
+
public labels: Record<string, string> = {};
|
|
225
|
+
public readonly eventSubject = new plugins.smartrx.rxjs.Subject<ITaskEvent>();
|
|
221
226
|
|
|
222
227
|
public get idle() {
|
|
223
228
|
return !this.running;
|
|
@@ -227,6 +232,38 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
227
232
|
this.lastError = undefined;
|
|
228
233
|
}
|
|
229
234
|
|
|
235
|
+
public setLabel(key: string, value: string): void {
|
|
236
|
+
this.labels[key] = value;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
public getLabel(key: string): string | undefined {
|
|
240
|
+
return this.labels[key];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
public removeLabel(key: string): boolean {
|
|
244
|
+
if (key in this.labels) {
|
|
245
|
+
delete this.labels[key];
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
public hasLabel(key: string, value?: string): boolean {
|
|
252
|
+
if (value !== undefined) {
|
|
253
|
+
return this.labels[key] === value;
|
|
254
|
+
}
|
|
255
|
+
return key in this.labels;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private emitEvent(type: TTaskEventType, extra?: Partial<ITaskEvent>): void {
|
|
259
|
+
this.eventSubject.next({
|
|
260
|
+
type,
|
|
261
|
+
task: this.getMetadata(),
|
|
262
|
+
timestamp: Date.now(),
|
|
263
|
+
...extra,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
230
267
|
public taskSetup: ITaskSetupFunction<T>;
|
|
231
268
|
public setupValue: T;
|
|
232
269
|
|
|
@@ -247,6 +284,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
247
284
|
taskSetup?: ITaskSetupFunction<T>;
|
|
248
285
|
steps?: TSteps;
|
|
249
286
|
catchErrors?: boolean;
|
|
287
|
+
labels?: Record<string, string>;
|
|
250
288
|
}) {
|
|
251
289
|
this.taskFunction = optionsArg.taskFunction;
|
|
252
290
|
this.preTask = optionsArg.preTask;
|
|
@@ -257,6 +295,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
257
295
|
this.name = optionsArg.name;
|
|
258
296
|
this.taskSetup = optionsArg.taskSetup;
|
|
259
297
|
this.catchErrors = optionsArg.catchErrors ?? false;
|
|
298
|
+
this.labels = optionsArg.labels ? { ...optionsArg.labels } : {};
|
|
260
299
|
|
|
261
300
|
// Initialize steps if provided
|
|
262
301
|
if (optionsArg.steps) {
|
|
@@ -309,8 +348,8 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
309
348
|
if (step) {
|
|
310
349
|
step.start();
|
|
311
350
|
this.currentStepName = stepName as string;
|
|
312
|
-
|
|
313
|
-
|
|
351
|
+
this.emitEvent('step', { stepName: stepName as string });
|
|
352
|
+
|
|
314
353
|
if (this.name) {
|
|
315
354
|
logger.log('info', `Task ${this.name}: Starting step "${stepName}" - ${step.description}`);
|
|
316
355
|
}
|
|
@@ -369,6 +408,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
369
408
|
cronSchedule: this.cronJob?.cronExpression,
|
|
370
409
|
lastError: this.lastError?.message,
|
|
371
410
|
errorCount: this.errorCount,
|
|
411
|
+
labels: { ...this.labels },
|
|
372
412
|
};
|
|
373
413
|
}
|
|
374
414
|
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
AbstractDistributedCoordinator,
|
|
5
5
|
type IDistributedTaskRequestResult,
|
|
6
6
|
} from './taskbuffer.classes.distributedcoordinator.js';
|
|
7
|
-
import type { ITaskMetadata, ITaskExecutionReport, IScheduledTaskInfo } from './taskbuffer.interfaces.js';
|
|
7
|
+
import type { ITaskMetadata, ITaskExecutionReport, IScheduledTaskInfo, ITaskEvent } from './taskbuffer.interfaces.js';
|
|
8
8
|
import { logger } from './taskbuffer.logging.js';
|
|
9
9
|
|
|
10
10
|
export interface ICronJob {
|
|
@@ -20,6 +20,8 @@ export interface ITaskManagerConstructorOptions {
|
|
|
20
20
|
export class TaskManager {
|
|
21
21
|
public randomId = plugins.smartunique.shortId();
|
|
22
22
|
public taskMap = new plugins.lik.ObjectMap<Task<any, any>>();
|
|
23
|
+
public readonly taskSubject = new plugins.smartrx.rxjs.Subject<ITaskEvent>();
|
|
24
|
+
private taskSubscriptions = new Map<Task<any, any>, plugins.smartrx.rxjs.Subscription>();
|
|
23
25
|
private cronJobManager = new plugins.smarttime.CronManager();
|
|
24
26
|
public options: ITaskManagerConstructorOptions = {
|
|
25
27
|
distributedCoordinator: null,
|
|
@@ -38,6 +40,19 @@ export class TaskManager {
|
|
|
38
40
|
throw new Error('Task must have a name to be added to taskManager');
|
|
39
41
|
}
|
|
40
42
|
this.taskMap.add(task);
|
|
43
|
+
const subscription = task.eventSubject.subscribe((event) => {
|
|
44
|
+
this.taskSubject.next(event);
|
|
45
|
+
});
|
|
46
|
+
this.taskSubscriptions.set(task, subscription);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public removeTask(task: Task<any, any>): void {
|
|
50
|
+
this.taskMap.remove(task);
|
|
51
|
+
const subscription = this.taskSubscriptions.get(task);
|
|
52
|
+
if (subscription) {
|
|
53
|
+
subscription.unsubscribe();
|
|
54
|
+
this.taskSubscriptions.delete(task);
|
|
55
|
+
}
|
|
41
56
|
}
|
|
42
57
|
|
|
43
58
|
public addAndScheduleTask(task: Task<any, any>, cronString: string) {
|
|
@@ -150,6 +165,10 @@ export class TaskManager {
|
|
|
150
165
|
if (this.options.distributedCoordinator) {
|
|
151
166
|
await this.options.distributedCoordinator.stop();
|
|
152
167
|
}
|
|
168
|
+
for (const [, subscription] of this.taskSubscriptions) {
|
|
169
|
+
subscription.unsubscribe();
|
|
170
|
+
}
|
|
171
|
+
this.taskSubscriptions.clear();
|
|
153
172
|
}
|
|
154
173
|
|
|
155
174
|
// Get metadata for a specific task
|
|
@@ -198,6 +217,14 @@ export class TaskManager {
|
|
|
198
217
|
return scheduledRuns;
|
|
199
218
|
}
|
|
200
219
|
|
|
220
|
+
public getTasksByLabel(key: string, value: string): Task<any, any>[] {
|
|
221
|
+
return this.taskMap.getArray().filter(task => task.labels[key] === value);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
public getTasksMetadataByLabel(key: string, value: string): ITaskMetadata[] {
|
|
225
|
+
return this.getTasksByLabel(key, value).map(task => task.getMetadata());
|
|
226
|
+
}
|
|
227
|
+
|
|
201
228
|
// Add, execute, and remove a task while collecting metadata
|
|
202
229
|
public async addExecuteRemoveTask<T, TSteps extends ReadonlyArray<{ name: string; description: string; percentage: number }>>(
|
|
203
230
|
task: Task<T, TSteps>,
|
|
@@ -236,7 +263,7 @@ export class TaskManager {
|
|
|
236
263
|
};
|
|
237
264
|
|
|
238
265
|
// Remove task from manager
|
|
239
|
-
this.
|
|
266
|
+
this.removeTask(task);
|
|
240
267
|
|
|
241
268
|
// Deschedule if it was scheduled
|
|
242
269
|
if (options?.schedule && task.name) {
|
|
@@ -260,7 +287,7 @@ export class TaskManager {
|
|
|
260
287
|
};
|
|
261
288
|
|
|
262
289
|
// Remove task from manager even on error
|
|
263
|
-
this.
|
|
290
|
+
this.removeTask(task);
|
|
264
291
|
|
|
265
292
|
// Deschedule if it was scheduled
|
|
266
293
|
if (options?.schedule && task.name) {
|
|
@@ -17,6 +17,7 @@ export interface ITaskMetadata {
|
|
|
17
17
|
timeout?: number;
|
|
18
18
|
lastError?: string;
|
|
19
19
|
errorCount?: number;
|
|
20
|
+
labels?: Record<string, string>;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export interface ITaskExecutionReport {
|
|
@@ -38,4 +39,14 @@ export interface IScheduledTaskInfo {
|
|
|
38
39
|
lastRun?: Date;
|
|
39
40
|
steps?: ITaskStep[];
|
|
40
41
|
metadata?: ITaskMetadata;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type TTaskEventType = 'started' | 'step' | 'completed' | 'failed';
|
|
45
|
+
|
|
46
|
+
export interface ITaskEvent {
|
|
47
|
+
type: TTaskEventType;
|
|
48
|
+
task: ITaskMetadata;
|
|
49
|
+
timestamp: number;
|
|
50
|
+
stepName?: string; // present when type === 'step'
|
|
51
|
+
error?: string; // present when type === 'failed'
|
|
41
52
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/taskbuffer',
|
|
6
|
-
version: '4.
|
|
6
|
+
version: '4.1.1',
|
|
7
7
|
description: 'A flexible task management library supporting TypeScript, allowing for task buffering, scheduling, and execution with dependency management.'
|
|
8
8
|
}
|