@push.rocks/taskbuffer 3.5.0 → 4.1.0

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.
Files changed (47) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/index.d.ts +1 -1
  3. package/dist_ts/taskbuffer.classes.bufferrunner.js +17 -4
  4. package/dist_ts/taskbuffer.classes.cyclecounter.d.ts +1 -0
  5. package/dist_ts/taskbuffer.classes.cyclecounter.js +14 -1
  6. package/dist_ts/taskbuffer.classes.task.d.ts +14 -1
  7. package/dist_ts/taskbuffer.classes.task.js +89 -8
  8. package/dist_ts/taskbuffer.classes.taskchain.d.ts +2 -2
  9. package/dist_ts/taskbuffer.classes.taskchain.js +14 -5
  10. package/dist_ts/taskbuffer.classes.taskdebounced.js +14 -3
  11. package/dist_ts/taskbuffer.classes.taskmanager.d.ts +6 -1
  12. package/dist_ts/taskbuffer.classes.taskmanager.js +39 -9
  13. package/dist_ts/taskbuffer.classes.taskparallel.js +4 -2
  14. package/dist_ts/taskbuffer.classes.taskrunner.d.ts +6 -6
  15. package/dist_ts/taskbuffer.classes.taskrunner.js +19 -13
  16. package/dist_ts/taskbuffer.interfaces.d.ts +11 -0
  17. package/dist_ts_web/ts/index.d.ts +1 -1
  18. package/dist_ts_web/ts/taskbuffer.classes.bufferrunner.js +17 -4
  19. package/dist_ts_web/ts/taskbuffer.classes.cyclecounter.d.ts +1 -0
  20. package/dist_ts_web/ts/taskbuffer.classes.cyclecounter.js +14 -1
  21. package/dist_ts_web/ts/taskbuffer.classes.task.d.ts +14 -1
  22. package/dist_ts_web/ts/taskbuffer.classes.task.js +89 -8
  23. package/dist_ts_web/ts/taskbuffer.classes.taskchain.d.ts +2 -2
  24. package/dist_ts_web/ts/taskbuffer.classes.taskchain.js +14 -5
  25. package/dist_ts_web/ts/taskbuffer.classes.taskdebounced.js +14 -3
  26. package/dist_ts_web/ts/taskbuffer.classes.taskmanager.d.ts +6 -1
  27. package/dist_ts_web/ts/taskbuffer.classes.taskmanager.js +39 -9
  28. package/dist_ts_web/ts/taskbuffer.classes.taskparallel.js +4 -2
  29. package/dist_ts_web/ts/taskbuffer.classes.taskrunner.d.ts +6 -6
  30. package/dist_ts_web/ts/taskbuffer.classes.taskrunner.js +19 -13
  31. package/dist_ts_web/ts/taskbuffer.interfaces.d.ts +11 -0
  32. package/dist_ts_web/ts_web/00_commitinfo_data.js +1 -1
  33. package/npmextra.json +14 -8
  34. package/package.json +10 -6
  35. package/readme.hints.md +42 -1
  36. package/ts/00_commitinfo_data.ts +1 -1
  37. package/ts/index.ts +1 -1
  38. package/ts/taskbuffer.classes.bufferrunner.ts +14 -3
  39. package/ts/taskbuffer.classes.cyclecounter.ts +12 -0
  40. package/ts/taskbuffer.classes.task.ts +111 -20
  41. package/ts/taskbuffer.classes.taskchain.ts +17 -10
  42. package/ts/taskbuffer.classes.taskdebounced.ts +12 -2
  43. package/ts/taskbuffer.classes.taskmanager.ts +41 -9
  44. package/ts/taskbuffer.classes.taskparallel.ts +3 -1
  45. package/ts/taskbuffer.classes.taskrunner.ts +17 -12
  46. package/ts/taskbuffer.interfaces.ts +13 -0
  47. package/ts_web/00_commitinfo_data.ts +1 -1
@@ -4,7 +4,8 @@ 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
+ import { logger } from './taskbuffer.logging.js';
8
9
 
9
10
  export interface ICronJob {
10
11
  cronString: string;
@@ -19,6 +20,8 @@ export interface ITaskManagerConstructorOptions {
19
20
  export class TaskManager {
20
21
  public randomId = plugins.smartunique.shortId();
21
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>();
22
25
  private cronJobManager = new plugins.smarttime.CronManager();
23
26
  public options: ITaskManagerConstructorOptions = {
24
27
  distributedCoordinator: null,
@@ -37,6 +40,19 @@ export class TaskManager {
37
40
  throw new Error('Task must have a name to be added to taskManager');
38
41
  }
39
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
+ }
40
56
  }
41
57
 
42
58
  public addAndScheduleTask(task: Task<any, any>, cronString: string) {
@@ -75,31 +91,35 @@ export class TaskManager {
75
91
  triggerTime,
76
92
  );
77
93
  if (!announcementResult.shouldTrigger) {
78
- console.log('Distributed coordinator result: NOT EXECUTING');
94
+ logger.log('info', 'Distributed coordinator result: NOT EXECUTING');
79
95
  return;
80
96
  } else {
81
- console.log('Distributed coordinator result: CHOSEN AND EXECUTING');
97
+ logger.log('info', 'Distributed coordinator result: CHOSEN AND EXECUTING');
82
98
  }
83
99
  }
84
- await task.trigger();
100
+ try {
101
+ await task.trigger();
102
+ } catch (err) {
103
+ logger.log('error', `TaskManager: scheduled task "${task.name || 'unnamed'}" failed: ${err instanceof Error ? err.message : String(err)}`);
104
+ }
85
105
  },
86
106
  );
87
107
  task.cronJob = cronJob;
88
108
  }
89
109
 
90
110
  private logTaskState(task: Task<any, any>) {
91
- console.log(`Taskbuffer schedule triggered task >>${task.name}<<`);
111
+ logger.log('info', `Taskbuffer schedule triggered task >>${task.name}<<`);
92
112
  const bufferState = task.buffered
93
113
  ? `buffered with max ${task.bufferMax} buffered calls`
94
114
  : `unbuffered`;
95
- console.log(`Task >>${task.name}<< is ${bufferState}`);
115
+ logger.log('info', `Task >>${task.name}<< is ${bufferState}`);
96
116
  }
97
117
 
98
118
  private async performDistributedConsultation(
99
119
  task: Task<any, any>,
100
120
  triggerTime: number,
101
121
  ): Promise<IDistributedTaskRequestResult> {
102
- console.log('Found a distributed coordinator, performing consultation.');
122
+ logger.log('info', 'Found a distributed coordinator, performing consultation.');
103
123
 
104
124
  return this.options.distributedCoordinator.fireDistributedTaskRequest({
105
125
  submitterId: this.randomId,
@@ -145,6 +165,10 @@ export class TaskManager {
145
165
  if (this.options.distributedCoordinator) {
146
166
  await this.options.distributedCoordinator.stop();
147
167
  }
168
+ for (const [, subscription] of this.taskSubscriptions) {
169
+ subscription.unsubscribe();
170
+ }
171
+ this.taskSubscriptions.clear();
148
172
  }
149
173
 
150
174
  // Get metadata for a specific task
@@ -193,6 +217,14 @@ export class TaskManager {
193
217
  return scheduledRuns;
194
218
  }
195
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
+
196
228
  // Add, execute, and remove a task while collecting metadata
197
229
  public async addExecuteRemoveTask<T, TSteps extends ReadonlyArray<{ name: string; description: string; percentage: number }>>(
198
230
  task: Task<T, TSteps>,
@@ -231,7 +263,7 @@ export class TaskManager {
231
263
  };
232
264
 
233
265
  // Remove task from manager
234
- this.taskMap.remove(task);
266
+ this.removeTask(task);
235
267
 
236
268
  // Deschedule if it was scheduled
237
269
  if (options?.schedule && task.name) {
@@ -255,7 +287,7 @@ export class TaskManager {
255
287
  };
256
288
 
257
289
  // Remove task from manager even on error
258
- this.taskMap.remove(task);
290
+ this.removeTask(task);
259
291
 
260
292
  // Deschedule if it was scheduled
261
293
  if (options?.schedule && task.name) {
@@ -13,7 +13,9 @@ export class Taskparallel extends Task {
13
13
  this.taskArray.forEach(function (taskArg) {
14
14
  promiseArray.push(taskArg.trigger());
15
15
  });
16
- Promise.all(promiseArray).then(done.resolve);
16
+ Promise.all(promiseArray)
17
+ .then((results) => done.resolve(results))
18
+ .catch((err) => done.reject(err));
17
19
  return done.promise;
18
20
  },
19
21
  },
@@ -1,13 +1,14 @@
1
1
  import * as plugins from './taskbuffer.plugins.js';
2
2
 
3
3
  import { Task } from './taskbuffer.classes.task.js';
4
+ import { logger } from './taskbuffer.logging.js';
4
5
 
5
6
  export class TaskRunner {
6
- public maxParrallelJobs: number = 1;
7
+ public maxParallelJobs: number = 1;
7
8
  public status: 'stopped' | 'running' = 'stopped';
8
9
  public runningTasks: plugins.lik.ObjectMap<Task> =
9
10
  new plugins.lik.ObjectMap<Task>();
10
- public qeuedTasks: Task[] = [];
11
+ public queuedTasks: Task[] = [];
11
12
 
12
13
  constructor() {
13
14
  this.runningTasks.eventSubject.subscribe(async (eventArg) => {
@@ -16,19 +17,19 @@ export class TaskRunner {
16
17
  }
17
18
 
18
19
  /**
19
- * adds a task to the qeue
20
+ * adds a task to the queue
20
21
  */
21
22
  public addTask(taskArg: Task) {
22
- this.qeuedTasks.push(taskArg);
23
+ this.queuedTasks.push(taskArg);
23
24
  this.checkExecution();
24
25
  }
25
26
 
26
27
  /**
27
28
  * set amount of parallel tasks
28
- * be careful, you might loose dependability of tasks
29
+ * be careful, you might lose dependability of tasks
29
30
  */
30
- public setMaxParallelJobs(maxParrallelJobsArg: number) {
31
- this.maxParrallelJobs = maxParrallelJobsArg;
31
+ public setMaxParallelJobs(maxParallelJobsArg: number) {
32
+ this.maxParallelJobs = maxParallelJobsArg;
32
33
  }
33
34
 
34
35
  /**
@@ -39,17 +40,21 @@ export class TaskRunner {
39
40
  }
40
41
 
41
42
  /**
42
- * checks wether execution is on point
43
+ * checks whether execution is on point
43
44
  */
44
45
  public async checkExecution() {
45
46
  if (
46
- this.runningTasks.getArray().length < this.maxParrallelJobs &&
47
+ this.runningTasks.getArray().length < this.maxParallelJobs &&
47
48
  this.status === 'running' &&
48
- this.qeuedTasks.length > 0
49
+ this.queuedTasks.length > 0
49
50
  ) {
50
- const nextJob = this.qeuedTasks.shift();
51
+ const nextJob = this.queuedTasks.shift();
51
52
  this.runningTasks.add(nextJob);
52
- await nextJob.trigger();
53
+ try {
54
+ await nextJob.trigger();
55
+ } catch (err) {
56
+ logger.log('error', `TaskRunner: task "${nextJob.name || 'unnamed'}" failed: ${err instanceof Error ? err.message : String(err)}`);
57
+ }
53
58
  this.runningTasks.remove(nextJob);
54
59
  this.checkExecution();
55
60
  }
@@ -15,6 +15,9 @@ export interface ITaskMetadata {
15
15
  buffered?: boolean;
16
16
  bufferMax?: number;
17
17
  timeout?: number;
18
+ lastError?: string;
19
+ errorCount?: number;
20
+ labels?: Record<string, string>;
18
21
  }
19
22
 
20
23
  export interface ITaskExecutionReport {
@@ -36,4 +39,14 @@ export interface IScheduledTaskInfo {
36
39
  lastRun?: Date;
37
40
  steps?: ITaskStep[];
38
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'
39
52
  }
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/taskbuffer',
6
- version: '3.5.0',
6
+ version: '4.1.0',
7
7
  description: 'A flexible task management library supporting TypeScript, allowing for task buffering, scheduling, and execution with dependency management.'
8
8
  }