@push.rocks/taskbuffer 3.5.0 → 4.0.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.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/taskbuffer.classes.bufferrunner.js +17 -4
- package/dist_ts/taskbuffer.classes.cyclecounter.d.ts +1 -0
- package/dist_ts/taskbuffer.classes.cyclecounter.js +14 -1
- package/dist_ts/taskbuffer.classes.task.d.ts +5 -0
- package/dist_ts/taskbuffer.classes.task.js +54 -7
- package/dist_ts/taskbuffer.classes.taskchain.d.ts +2 -2
- package/dist_ts/taskbuffer.classes.taskchain.js +14 -5
- package/dist_ts/taskbuffer.classes.taskdebounced.js +14 -3
- package/dist_ts/taskbuffer.classes.taskmanager.js +13 -7
- package/dist_ts/taskbuffer.classes.taskparallel.js +4 -2
- package/dist_ts/taskbuffer.classes.taskrunner.d.ts +6 -6
- package/dist_ts/taskbuffer.classes.taskrunner.js +19 -13
- package/dist_ts/taskbuffer.interfaces.d.ts +2 -0
- package/dist_ts_web/ts/taskbuffer.classes.bufferrunner.js +17 -4
- package/dist_ts_web/ts/taskbuffer.classes.cyclecounter.d.ts +1 -0
- package/dist_ts_web/ts/taskbuffer.classes.cyclecounter.js +14 -1
- package/dist_ts_web/ts/taskbuffer.classes.task.d.ts +5 -0
- package/dist_ts_web/ts/taskbuffer.classes.task.js +54 -7
- package/dist_ts_web/ts/taskbuffer.classes.taskchain.d.ts +2 -2
- package/dist_ts_web/ts/taskbuffer.classes.taskchain.js +14 -5
- package/dist_ts_web/ts/taskbuffer.classes.taskdebounced.js +14 -3
- package/dist_ts_web/ts/taskbuffer.classes.taskmanager.js +13 -7
- package/dist_ts_web/ts/taskbuffer.classes.taskparallel.js +4 -2
- package/dist_ts_web/ts/taskbuffer.classes.taskrunner.d.ts +6 -6
- package/dist_ts_web/ts/taskbuffer.classes.taskrunner.js +19 -13
- package/dist_ts_web/ts/taskbuffer.interfaces.d.ts +2 -0
- package/dist_ts_web/ts_web/00_commitinfo_data.js +1 -1
- package/npmextra.json +14 -8
- package/package.json +10 -6
- package/readme.hints.md +28 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/taskbuffer.classes.bufferrunner.ts +14 -3
- package/ts/taskbuffer.classes.cyclecounter.ts +12 -0
- package/ts/taskbuffer.classes.task.ts +68 -17
- package/ts/taskbuffer.classes.taskchain.ts +17 -10
- package/ts/taskbuffer.classes.taskdebounced.ts +12 -2
- package/ts/taskbuffer.classes.taskmanager.ts +11 -6
- package/ts/taskbuffer.classes.taskparallel.ts +3 -1
- package/ts/taskbuffer.classes.taskrunner.ts +17 -12
- package/ts/taskbuffer.interfaces.ts +2 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
package/npmextra.json
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"npmGlobalTools": [],
|
|
4
|
-
"npmAccessLevel": "public",
|
|
5
|
-
"npmRegistryUrl": "registry.npmjs.org"
|
|
6
|
-
},
|
|
7
|
-
"gitzone": {
|
|
2
|
+
"@git.zone/cli": {
|
|
8
3
|
"projectType": "npm",
|
|
9
4
|
"module": {
|
|
10
5
|
"githost": "code.foss.global",
|
|
@@ -25,9 +20,20 @@
|
|
|
25
20
|
"debounced tasks",
|
|
26
21
|
"distributed coordination"
|
|
27
22
|
]
|
|
23
|
+
},
|
|
24
|
+
"release": {
|
|
25
|
+
"registries": [
|
|
26
|
+
"https://verdaccio.lossless.digital",
|
|
27
|
+
"https://registry.npmjs.org"
|
|
28
|
+
],
|
|
29
|
+
"accessLevel": "public"
|
|
28
30
|
}
|
|
29
31
|
},
|
|
30
|
-
"tsdoc": {
|
|
32
|
+
"@git.zone/tsdoc": {
|
|
31
33
|
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
|
34
|
+
},
|
|
35
|
+
"@ship.zone/szci": {
|
|
36
|
+
"npmGlobalTools": [],
|
|
37
|
+
"npmRegistryUrl": "registry.npmjs.org"
|
|
32
38
|
}
|
|
33
|
-
}
|
|
39
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/taskbuffer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A flexible task management library supporting TypeScript, allowing for task buffering, scheduling, and execution with dependency management.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
|
7
7
|
"typings": "dist_ts/index.d.ts",
|
|
8
8
|
"type": "module",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "(tstest test/ --verbose --logfile --timeout 120)",
|
|
11
|
+
"build": "(tsbuild tsfolders)",
|
|
12
|
+
"buildDocs": "tsdoc"
|
|
13
|
+
},
|
|
9
14
|
"repository": {
|
|
10
15
|
"type": "git",
|
|
11
16
|
"url": "https://code.foss.global/push.rocks/taskbuffer.git"
|
|
@@ -60,9 +65,8 @@
|
|
|
60
65
|
"browserslist": [
|
|
61
66
|
"last 1 chrome versions"
|
|
62
67
|
],
|
|
63
|
-
"
|
|
64
|
-
|
|
65
|
-
"
|
|
66
|
-
"buildDocs": "tsdoc"
|
|
68
|
+
"packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748",
|
|
69
|
+
"pnpm": {
|
|
70
|
+
"overrides": {}
|
|
67
71
|
}
|
|
68
|
-
}
|
|
72
|
+
}
|
package/readme.hints.md
CHANGED
|
@@ -1 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
# Taskbuffer Hints
|
|
2
|
+
|
|
3
|
+
## Error Handling (v3.6.0+)
|
|
4
|
+
- `Task` now has `catchErrors` constructor option (default: `false`)
|
|
5
|
+
- Default behavior: `trigger()` rejects when taskFunction throws (breaking change from pre-3.6)
|
|
6
|
+
- Set `catchErrors: true` to swallow errors (old behavior) - returns `undefined` on error
|
|
7
|
+
- Error state tracked via `lastError?: Error`, `errorCount: number`, `clearError()`
|
|
8
|
+
- `getMetadata()` status uses all four values: `'idle'` | `'running'` | `'completed'` | `'failed'`
|
|
9
|
+
- All peripheral classes (Taskchain, Taskparallel, TaskRunner, BufferRunner, TaskDebounced, TaskManager) have proper error propagation/handling
|
|
10
|
+
- `console.log` calls replaced with `logger.log()` throughout
|
|
11
|
+
|
|
12
|
+
## Breaking API Rename (TaskRunner)
|
|
13
|
+
- `maxParrallelJobs` → `maxParallelJobs`
|
|
14
|
+
- `qeuedTasks` → `queuedTasks`
|
|
15
|
+
- JSDoc typos fixed: "qeue" → "queue", "wether" → "whether", "loose" → "lose"
|
|
16
|
+
- The `setMaxParallelJobs()` parameter also renamed from `maxParrallelJobsArg` to `maxParallelJobsArg`
|
|
17
|
+
|
|
18
|
+
## Error Context Improvements
|
|
19
|
+
- **TaskChain**: Errors now wrap the original with context: chain name, failing task name, and task index. Original error preserved via `.cause`
|
|
20
|
+
- **BufferRunner**: When `catchErrors: false`, buffered task errors now reject the trigger promise (via `CycleCounter.informOfCycleError`) instead of silently resolving with `undefined`
|
|
21
|
+
- **TaskChain stubs completed**: `removeTask(task)` returns `boolean`, `shiftTask()` returns `Task | undefined`
|
|
22
|
+
|
|
23
|
+
## Project Structure
|
|
24
|
+
- Source in `ts/`, web components in `ts_web/`
|
|
25
|
+
- Tests in `test/` - naming: `*.node.ts`, `*.browser.ts`, `*.both.ts`
|
|
26
|
+
- Logger: `ts/taskbuffer.logging.ts` exports `logger` (ConsoleLog from smartlog)
|
|
27
|
+
- Build: `pnpm build` (tsbuild tsfolders)
|
|
28
|
+
- Test: `pnpm test` or `tstest test/test.XX.name.ts --verbose`
|
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: '
|
|
6
|
+
version: '4.0.0',
|
|
7
7
|
description: 'A flexible task management library supporting TypeScript, allowing for task buffering, scheduling, and execution with dependency management.'
|
|
8
8
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Task } from './taskbuffer.classes.task.js';
|
|
2
|
+
import { logger } from './taskbuffer.logging.js';
|
|
2
3
|
|
|
3
4
|
export class BufferRunner {
|
|
4
5
|
public task: Task;
|
|
@@ -24,9 +25,19 @@ export class BufferRunner {
|
|
|
24
25
|
private async _run(x: any) {
|
|
25
26
|
this.task.running = true;
|
|
26
27
|
while (this.bufferCounter > 0) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
try {
|
|
29
|
+
const result = await Task.runTask(this.task, { x: x });
|
|
30
|
+
this.bufferCounter--;
|
|
31
|
+
this.task.cycleCounter.informOfCycle(result);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
logger.log('error', `BufferRunner: task "${this.task.name || 'unnamed'}" failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
34
|
+
this.bufferCounter--;
|
|
35
|
+
if (this.task.catchErrors) {
|
|
36
|
+
this.task.cycleCounter.informOfCycle(undefined);
|
|
37
|
+
} else {
|
|
38
|
+
this.task.cycleCounter.informOfCycleError(err instanceof Error ? err : new Error(String(err)));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
30
41
|
}
|
|
31
42
|
this.task.running = false;
|
|
32
43
|
}
|
|
@@ -33,4 +33,16 @@ export class CycleCounter {
|
|
|
33
33
|
});
|
|
34
34
|
this.cycleObjectArray = newCycleObjectArray;
|
|
35
35
|
}
|
|
36
|
+
public informOfCycleError(err: Error) {
|
|
37
|
+
const newCycleObjectArray: ICycleObject[] = [];
|
|
38
|
+
this.cycleObjectArray.forEach((cycleObjectArg) => {
|
|
39
|
+
cycleObjectArg.cycleCounter--;
|
|
40
|
+
if (cycleObjectArg.cycleCounter <= 0) {
|
|
41
|
+
cycleObjectArg.deferred.reject(err);
|
|
42
|
+
} else {
|
|
43
|
+
newCycleObjectArray.push(cycleObjectArg);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
this.cycleObjectArray = newCycleObjectArray;
|
|
47
|
+
}
|
|
36
48
|
}
|
|
@@ -87,24 +87,37 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
87
87
|
taskToRun.running = true;
|
|
88
88
|
taskToRun.runCount++;
|
|
89
89
|
taskToRun.lastRun = new Date();
|
|
90
|
-
|
|
91
|
-
// Reset steps at the beginning of task execution
|
|
90
|
+
|
|
91
|
+
// Reset steps and error state at the beginning of task execution
|
|
92
92
|
taskToRun.resetSteps();
|
|
93
|
+
taskToRun.lastError = undefined;
|
|
93
94
|
|
|
94
|
-
done.promise
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
done.promise
|
|
96
|
+
.then(async () => {
|
|
97
|
+
taskToRun.running = false;
|
|
98
|
+
|
|
99
|
+
// Complete all steps when task finishes
|
|
100
|
+
taskToRun.completeAllSteps();
|
|
101
|
+
|
|
102
|
+
// When the task has finished running, resolve the finished promise
|
|
103
|
+
taskToRun.resolveFinished();
|
|
99
104
|
|
|
100
|
-
|
|
101
|
-
|
|
105
|
+
// Create a new finished promise for the next run
|
|
106
|
+
taskToRun.finished = new Promise((resolve) => {
|
|
107
|
+
taskToRun.resolveFinished = resolve;
|
|
108
|
+
});
|
|
109
|
+
})
|
|
110
|
+
.catch((err) => {
|
|
111
|
+
taskToRun.running = false;
|
|
102
112
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
113
|
+
// Resolve finished so blocking dependants don't hang
|
|
114
|
+
taskToRun.resolveFinished();
|
|
115
|
+
|
|
116
|
+
// Create a new finished promise for the next run
|
|
117
|
+
taskToRun.finished = new Promise((resolve) => {
|
|
118
|
+
taskToRun.resolveFinished = resolve;
|
|
119
|
+
});
|
|
106
120
|
});
|
|
107
|
-
});
|
|
108
121
|
|
|
109
122
|
const options = {
|
|
110
123
|
...{ x: undefined, touchedTasksArray: [] },
|
|
@@ -133,7 +146,13 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
133
146
|
try {
|
|
134
147
|
return await taskToRun.taskFunction(x, taskToRun.setupValue);
|
|
135
148
|
} catch (e) {
|
|
136
|
-
|
|
149
|
+
taskToRun.lastError = e instanceof Error ? e : new Error(String(e));
|
|
150
|
+
taskToRun.errorCount++;
|
|
151
|
+
logger.log('error', `Task "${taskToRun.name || 'unnamed'}" failed: ${taskToRun.lastError.message}`);
|
|
152
|
+
if (taskToRun.catchErrors) {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
throw e;
|
|
137
156
|
}
|
|
138
157
|
})
|
|
139
158
|
.then((x) => {
|
|
@@ -155,10 +174,18 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
155
174
|
done.resolve(x);
|
|
156
175
|
})
|
|
157
176
|
.catch((err) => {
|
|
158
|
-
|
|
177
|
+
done.reject(err);
|
|
159
178
|
});
|
|
160
179
|
localDeferred.resolve();
|
|
161
|
-
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
return await done.promise;
|
|
183
|
+
} catch (err) {
|
|
184
|
+
if (taskToRun.catchErrors) {
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
throw err;
|
|
188
|
+
}
|
|
162
189
|
};
|
|
163
190
|
|
|
164
191
|
public name: string;
|
|
@@ -187,10 +214,19 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
187
214
|
public lastRun?: Date;
|
|
188
215
|
public runCount: number = 0;
|
|
189
216
|
|
|
217
|
+
// Error handling
|
|
218
|
+
public catchErrors: boolean = false;
|
|
219
|
+
public lastError?: Error;
|
|
220
|
+
public errorCount: number = 0;
|
|
221
|
+
|
|
190
222
|
public get idle() {
|
|
191
223
|
return !this.running;
|
|
192
224
|
}
|
|
193
225
|
|
|
226
|
+
public clearError(): void {
|
|
227
|
+
this.lastError = undefined;
|
|
228
|
+
}
|
|
229
|
+
|
|
194
230
|
public taskSetup: ITaskSetupFunction<T>;
|
|
195
231
|
public setupValue: T;
|
|
196
232
|
|
|
@@ -210,6 +246,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
210
246
|
name?: string;
|
|
211
247
|
taskSetup?: ITaskSetupFunction<T>;
|
|
212
248
|
steps?: TSteps;
|
|
249
|
+
catchErrors?: boolean;
|
|
213
250
|
}) {
|
|
214
251
|
this.taskFunction = optionsArg.taskFunction;
|
|
215
252
|
this.preTask = optionsArg.preTask;
|
|
@@ -219,6 +256,7 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
219
256
|
this.execDelay = optionsArg.execDelay;
|
|
220
257
|
this.name = optionsArg.name;
|
|
221
258
|
this.taskSetup = optionsArg.taskSetup;
|
|
259
|
+
this.catchErrors = optionsArg.catchErrors ?? false;
|
|
222
260
|
|
|
223
261
|
// Initialize steps if provided
|
|
224
262
|
if (optionsArg.steps) {
|
|
@@ -306,10 +344,21 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
306
344
|
|
|
307
345
|
// Get task metadata
|
|
308
346
|
public getMetadata(): ITaskMetadata {
|
|
347
|
+
let status: 'idle' | 'running' | 'completed' | 'failed';
|
|
348
|
+
if (this.running) {
|
|
349
|
+
status = 'running';
|
|
350
|
+
} else if (this.lastError) {
|
|
351
|
+
status = 'failed';
|
|
352
|
+
} else if (this.runCount > 0) {
|
|
353
|
+
status = 'completed';
|
|
354
|
+
} else {
|
|
355
|
+
status = 'idle';
|
|
356
|
+
}
|
|
357
|
+
|
|
309
358
|
return {
|
|
310
359
|
name: this.name || 'unnamed',
|
|
311
360
|
version: this.version,
|
|
312
|
-
status
|
|
361
|
+
status,
|
|
313
362
|
steps: this.getStepsMetadata(),
|
|
314
363
|
currentStep: this.currentStepName,
|
|
315
364
|
currentProgress: this.getProgress(),
|
|
@@ -318,6 +367,8 @@ export class Task<T = undefined, TSteps extends ReadonlyArray<{ name: string; de
|
|
|
318
367
|
bufferMax: this.bufferMax,
|
|
319
368
|
timeout: this.timeout,
|
|
320
369
|
cronSchedule: this.cronJob?.cronExpression,
|
|
370
|
+
lastError: this.lastError?.message,
|
|
371
|
+
errorCount: this.errorCount,
|
|
321
372
|
};
|
|
322
373
|
}
|
|
323
374
|
|
|
@@ -27,18 +27,20 @@ export class Taskchain extends Task {
|
|
|
27
27
|
let taskCounter = 0; // counter for iterating async over the taskArray
|
|
28
28
|
const iterateTasks = (x: any) => {
|
|
29
29
|
if (typeof this.taskArray[taskCounter] !== 'undefined') {
|
|
30
|
-
|
|
31
|
-
this.name + ' running: Task' + this.taskArray[taskCounter].name,
|
|
32
|
-
);
|
|
30
|
+
logger.log('info', `${this.name} running: Task ${this.taskArray[taskCounter].name}`);
|
|
33
31
|
this.taskArray[taskCounter].trigger(x).then((x) => {
|
|
34
32
|
logger.log('info', this.taskArray[taskCounter].name);
|
|
35
33
|
taskCounter++;
|
|
36
34
|
iterateTasks(x);
|
|
35
|
+
}).catch((err) => {
|
|
36
|
+
const chainError = new Error(
|
|
37
|
+
`Taskchain "${this.name}": task "${this.taskArray[taskCounter].name || 'unnamed'}" (index ${taskCounter}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
38
|
+
);
|
|
39
|
+
(chainError as any).cause = err;
|
|
40
|
+
done.reject(chainError);
|
|
37
41
|
});
|
|
38
42
|
} else {
|
|
39
|
-
|
|
40
|
-
'Taskchain "' + this.name + '" completed successfully',
|
|
41
|
-
);
|
|
43
|
+
logger.log('info', `Taskchain "${this.name}" completed successfully`);
|
|
42
44
|
done.resolve(x);
|
|
43
45
|
}
|
|
44
46
|
};
|
|
@@ -53,10 +55,15 @@ export class Taskchain extends Task {
|
|
|
53
55
|
addTask(taskArg: Task) {
|
|
54
56
|
this.taskArray.push(taskArg);
|
|
55
57
|
}
|
|
56
|
-
removeTask(taskArg: Task) {
|
|
57
|
-
|
|
58
|
+
removeTask(taskArg: Task): boolean {
|
|
59
|
+
const index = this.taskArray.indexOf(taskArg);
|
|
60
|
+
if (index === -1) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
this.taskArray.splice(index, 1);
|
|
64
|
+
return true;
|
|
58
65
|
}
|
|
59
|
-
shiftTask() {
|
|
60
|
-
|
|
66
|
+
shiftTask(): Task | undefined {
|
|
67
|
+
return this.taskArray.shift();
|
|
61
68
|
}
|
|
62
69
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as plugins from './taskbuffer.plugins.js';
|
|
2
2
|
|
|
3
3
|
import { Task, type ITaskFunction } from './taskbuffer.classes.task.js';
|
|
4
|
+
import { logger } from './taskbuffer.logging.js';
|
|
4
5
|
|
|
5
6
|
export class TaskDebounced<T = unknown> extends Task {
|
|
6
7
|
private _debouncedTaskFunction: ITaskFunction;
|
|
@@ -22,8 +23,17 @@ export class TaskDebounced<T = unknown> extends Task {
|
|
|
22
23
|
.pipe(
|
|
23
24
|
plugins.smartrx.rxjs.ops.debounceTime(optionsArg.debounceTimeInMillis),
|
|
24
25
|
)
|
|
25
|
-
.subscribe(
|
|
26
|
-
|
|
26
|
+
.subscribe({
|
|
27
|
+
next: async (x) => {
|
|
28
|
+
try {
|
|
29
|
+
await this.taskFunction(x);
|
|
30
|
+
} catch (err) {
|
|
31
|
+
logger.log('error', `TaskDebounced "${this.name || 'unnamed'}" failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
error: (err) => {
|
|
35
|
+
logger.log('error', `TaskDebounced "${this.name || 'unnamed'}" observable error: ${err instanceof Error ? err.message : String(err)}`);
|
|
36
|
+
},
|
|
27
37
|
});
|
|
28
38
|
}
|
|
29
39
|
}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
type IDistributedTaskRequestResult,
|
|
6
6
|
} from './taskbuffer.classes.distributedcoordinator.js';
|
|
7
7
|
import type { ITaskMetadata, ITaskExecutionReport, IScheduledTaskInfo } from './taskbuffer.interfaces.js';
|
|
8
|
+
import { logger } from './taskbuffer.logging.js';
|
|
8
9
|
|
|
9
10
|
export interface ICronJob {
|
|
10
11
|
cronString: string;
|
|
@@ -75,31 +76,35 @@ export class TaskManager {
|
|
|
75
76
|
triggerTime,
|
|
76
77
|
);
|
|
77
78
|
if (!announcementResult.shouldTrigger) {
|
|
78
|
-
|
|
79
|
+
logger.log('info', 'Distributed coordinator result: NOT EXECUTING');
|
|
79
80
|
return;
|
|
80
81
|
} else {
|
|
81
|
-
|
|
82
|
+
logger.log('info', 'Distributed coordinator result: CHOSEN AND EXECUTING');
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
+
try {
|
|
86
|
+
await task.trigger();
|
|
87
|
+
} catch (err) {
|
|
88
|
+
logger.log('error', `TaskManager: scheduled task "${task.name || 'unnamed'}" failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
89
|
+
}
|
|
85
90
|
},
|
|
86
91
|
);
|
|
87
92
|
task.cronJob = cronJob;
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
private logTaskState(task: Task<any, any>) {
|
|
91
|
-
|
|
96
|
+
logger.log('info', `Taskbuffer schedule triggered task >>${task.name}<<`);
|
|
92
97
|
const bufferState = task.buffered
|
|
93
98
|
? `buffered with max ${task.bufferMax} buffered calls`
|
|
94
99
|
: `unbuffered`;
|
|
95
|
-
|
|
100
|
+
logger.log('info', `Task >>${task.name}<< is ${bufferState}`);
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
private async performDistributedConsultation(
|
|
99
104
|
task: Task<any, any>,
|
|
100
105
|
triggerTime: number,
|
|
101
106
|
): Promise<IDistributedTaskRequestResult> {
|
|
102
|
-
|
|
107
|
+
logger.log('info', 'Found a distributed coordinator, performing consultation.');
|
|
103
108
|
|
|
104
109
|
return this.options.distributedCoordinator.fireDistributedTaskRequest({
|
|
105
110
|
submitterId: this.randomId,
|
|
@@ -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)
|
|
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
|
|
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
|
|
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
|
|
20
|
+
* adds a task to the queue
|
|
20
21
|
*/
|
|
21
22
|
public addTask(taskArg: Task) {
|
|
22
|
-
this.
|
|
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
|
|
29
|
+
* be careful, you might lose dependability of tasks
|
|
29
30
|
*/
|
|
30
|
-
public setMaxParallelJobs(
|
|
31
|
-
this.
|
|
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
|
|
43
|
+
* checks whether execution is on point
|
|
43
44
|
*/
|
|
44
45
|
public async checkExecution() {
|
|
45
46
|
if (
|
|
46
|
-
this.runningTasks.getArray().length < this.
|
|
47
|
+
this.runningTasks.getArray().length < this.maxParallelJobs &&
|
|
47
48
|
this.status === 'running' &&
|
|
48
|
-
this.
|
|
49
|
+
this.queuedTasks.length > 0
|
|
49
50
|
) {
|
|
50
|
-
const nextJob = this.
|
|
51
|
+
const nextJob = this.queuedTasks.shift();
|
|
51
52
|
this.runningTasks.add(nextJob);
|
|
52
|
-
|
|
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
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/taskbuffer',
|
|
6
|
-
version: '
|
|
6
|
+
version: '4.0.0',
|
|
7
7
|
description: 'A flexible task management library supporting TypeScript, allowing for task buffering, scheduling, and execution with dependency management.'
|
|
8
8
|
}
|