@push.rocks/taskbuffer 3.0.10
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/LICENSE +21 -0
- package/dist_bundle/bundle.js +18376 -0
- package/dist_bundle/bundle.js.map +7 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/index.d.ts +10 -0
- package/dist_ts/index.js +10 -0
- package/dist_ts/taskbuffer.classes.bufferrunner.d.ts +8 -0
- package/dist_ts/taskbuffer.classes.bufferrunner.js +35 -0
- package/dist_ts/taskbuffer.classes.cyclecounter.d.ts +13 -0
- package/dist_ts/taskbuffer.classes.cyclecounter.js +31 -0
- package/dist_ts/taskbuffer.classes.distributedcoordinator.d.ts +29 -0
- package/dist_ts/taskbuffer.classes.distributedcoordinator.js +5 -0
- package/dist_ts/taskbuffer.classes.task.d.ts +84 -0
- package/dist_ts/taskbuffer.classes.task.js +159 -0
- package/dist_ts/taskbuffer.classes.taskchain.d.ts +14 -0
- package/dist_ts/taskbuffer.classes.taskchain.js +51 -0
- package/dist_ts/taskbuffer.classes.taskdebounced.d.ts +10 -0
- package/dist_ts/taskbuffer.classes.taskdebounced.js +20 -0
- package/dist_ts/taskbuffer.classes.taskmanager.d.ts +68 -0
- package/dist_ts/taskbuffer.classes.taskmanager.js +129 -0
- package/dist_ts/taskbuffer.classes.taskonce.d.ts +11 -0
- package/dist_ts/taskbuffer.classes.taskonce.js +20 -0
- package/dist_ts/taskbuffer.classes.taskparallel.d.ts +7 -0
- package/dist_ts/taskbuffer.classes.taskparallel.js +23 -0
- package/dist_ts/taskbuffer.classes.taskrunner.d.ts +30 -0
- package/dist_ts/taskbuffer.classes.taskrunner.js +54 -0
- package/dist_ts/taskbuffer.logging.d.ts +2 -0
- package/dist_ts/taskbuffer.logging.js +3 -0
- package/dist_ts/taskbuffer.plugins.d.ts +8 -0
- package/dist_ts/taskbuffer.plugins.js +9 -0
- package/npmextra.json +18 -0
- package/package.json +62 -0
- package/readme.md +63 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/index.ts +12 -0
- package/ts/taskbuffer.classes.bufferrunner.ts +39 -0
- package/ts/taskbuffer.classes.cyclecounter.ts +36 -0
- package/ts/taskbuffer.classes.distributedcoordinator.ts +34 -0
- package/ts/taskbuffer.classes.task.ts +236 -0
- package/ts/taskbuffer.classes.taskchain.ts +58 -0
- package/ts/taskbuffer.classes.taskdebounced.ts +27 -0
- package/ts/taskbuffer.classes.taskmanager.ts +155 -0
- package/ts/taskbuffer.classes.taskonce.ts +21 -0
- package/ts/taskbuffer.classes.taskparallel.ts +24 -0
- package/ts/taskbuffer.classes.taskrunner.ts +63 -0
- package/ts/taskbuffer.logging.ts +3 -0
- package/ts/taskbuffer.plugins.ts +9 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import * as plugins from './taskbuffer.plugins.js';
|
|
2
|
+
import { BufferRunner } from './taskbuffer.classes.bufferrunner.js';
|
|
3
|
+
import { CycleCounter } from './taskbuffer.classes.cyclecounter.js';
|
|
4
|
+
|
|
5
|
+
import { logger } from './taskbuffer.logging.js';
|
|
6
|
+
|
|
7
|
+
export interface ITaskFunction {
|
|
8
|
+
(x?: any): PromiseLike<any>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type TPreOrAfterTaskFunction = () => Task;
|
|
12
|
+
|
|
13
|
+
export class Task {
|
|
14
|
+
// STATIC
|
|
15
|
+
public static extractTask(preOrAfterTaskArg: Task | TPreOrAfterTaskFunction): Task {
|
|
16
|
+
switch (true) {
|
|
17
|
+
case !preOrAfterTaskArg:
|
|
18
|
+
return null;
|
|
19
|
+
case preOrAfterTaskArg instanceof Task:
|
|
20
|
+
return preOrAfterTaskArg as Task;
|
|
21
|
+
case typeof preOrAfterTaskArg === 'function':
|
|
22
|
+
const taskFunction = preOrAfterTaskArg as TPreOrAfterTaskFunction;
|
|
23
|
+
return taskFunction();
|
|
24
|
+
default:
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public static emptyTaskFunction: ITaskFunction = function (x) {
|
|
30
|
+
const done = plugins.smartpromise.defer();
|
|
31
|
+
done.resolve();
|
|
32
|
+
return done.promise;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
public static isTask = (taskArg: Task): boolean => {
|
|
36
|
+
if (taskArg instanceof Task && typeof taskArg.taskFunction === 'function') {
|
|
37
|
+
return true;
|
|
38
|
+
} else {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
public static isTaskTouched = (
|
|
44
|
+
taskArg: Task | TPreOrAfterTaskFunction,
|
|
45
|
+
touchedTasksArray: Task[]
|
|
46
|
+
): boolean => {
|
|
47
|
+
const taskToCheck = Task.extractTask(taskArg);
|
|
48
|
+
let result = false;
|
|
49
|
+
for (const keyArg in touchedTasksArray) {
|
|
50
|
+
if (taskToCheck === touchedTasksArray[keyArg]) {
|
|
51
|
+
result = true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
public static runTask = async (
|
|
58
|
+
taskArg: Task | TPreOrAfterTaskFunction,
|
|
59
|
+
optionsArg: { x?: any; touchedTasksArray?: Task[] }
|
|
60
|
+
) => {
|
|
61
|
+
// extracts the task in case it is specified as a return value of a function
|
|
62
|
+
const taskToRun = Task.extractTask(taskArg);
|
|
63
|
+
const done = plugins.smartpromise.defer();
|
|
64
|
+
|
|
65
|
+
// pay respect to execDelay
|
|
66
|
+
if (taskToRun.execDelay) {
|
|
67
|
+
await plugins.smartdelay.delayFor(taskToRun.execDelay);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// set running params
|
|
71
|
+
taskToRun.running = true;
|
|
72
|
+
|
|
73
|
+
done.promise.then(async () => {
|
|
74
|
+
taskToRun.running = false;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// handle options
|
|
78
|
+
const options = {
|
|
79
|
+
...{ x: undefined, touchedTasksArray: [] },
|
|
80
|
+
...optionsArg,
|
|
81
|
+
};
|
|
82
|
+
const x = options.x;
|
|
83
|
+
const touchedTasksArray: Task[] = options.touchedTasksArray;
|
|
84
|
+
|
|
85
|
+
touchedTasksArray.push(taskToRun);
|
|
86
|
+
|
|
87
|
+
// run the task cascade
|
|
88
|
+
const localDeferred = plugins.smartpromise.defer();
|
|
89
|
+
localDeferred.promise
|
|
90
|
+
.then(() => {
|
|
91
|
+
// lets run any preTask
|
|
92
|
+
|
|
93
|
+
if (taskToRun.preTask && !Task.isTaskTouched(taskToRun.preTask, touchedTasksArray)) {
|
|
94
|
+
return Task.runTask(taskToRun.preTask, { x, touchedTasksArray });
|
|
95
|
+
} else {
|
|
96
|
+
const done2 = plugins.smartpromise.defer();
|
|
97
|
+
done2.resolve(x);
|
|
98
|
+
return done2.promise;
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
.then(async (x) => {
|
|
102
|
+
// lets run the main task
|
|
103
|
+
try {
|
|
104
|
+
return await taskToRun.taskFunction(x);
|
|
105
|
+
} catch (e) {
|
|
106
|
+
console.log(e);
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
.then((x) => {
|
|
110
|
+
if (taskToRun.afterTask && !Task.isTaskTouched(taskToRun.afterTask, touchedTasksArray)) {
|
|
111
|
+
return Task.runTask(taskToRun.afterTask, { x: x, touchedTasksArray: touchedTasksArray });
|
|
112
|
+
} else {
|
|
113
|
+
const done2 = plugins.smartpromise.defer();
|
|
114
|
+
done2.resolve(x);
|
|
115
|
+
return done2.promise;
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
.then((x) => {
|
|
119
|
+
done.resolve(x);
|
|
120
|
+
})
|
|
121
|
+
.catch((err) => {
|
|
122
|
+
console.log(err);
|
|
123
|
+
});
|
|
124
|
+
localDeferred.resolve();
|
|
125
|
+
return await done.promise;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// INSTANCE
|
|
129
|
+
// mandatory properties
|
|
130
|
+
public name: string;
|
|
131
|
+
/**
|
|
132
|
+
* the version of the task
|
|
133
|
+
* should follow semver
|
|
134
|
+
* might be important for DistributedCoordinator
|
|
135
|
+
*/
|
|
136
|
+
public version: string;
|
|
137
|
+
public taskFunction: ITaskFunction;
|
|
138
|
+
public buffered: boolean;
|
|
139
|
+
public cronJob: plugins.smarttime.CronJob;
|
|
140
|
+
|
|
141
|
+
public bufferMax: number;
|
|
142
|
+
public execDelay: number;
|
|
143
|
+
public timeout: number;
|
|
144
|
+
|
|
145
|
+
// tasks to run before and after
|
|
146
|
+
public preTask: Task | TPreOrAfterTaskFunction;
|
|
147
|
+
public afterTask: Task | TPreOrAfterTaskFunction;
|
|
148
|
+
|
|
149
|
+
// initialize by default
|
|
150
|
+
public running: boolean = false;
|
|
151
|
+
public bufferRunner = new BufferRunner(this);
|
|
152
|
+
public cycleCounter = new CycleCounter(this);
|
|
153
|
+
|
|
154
|
+
public idle: boolean = true;
|
|
155
|
+
private _state: string = 'ready';
|
|
156
|
+
|
|
157
|
+
constructor(optionsArg: {
|
|
158
|
+
/**
|
|
159
|
+
* the task function to run, must return promise
|
|
160
|
+
*/
|
|
161
|
+
taskFunction: ITaskFunction;
|
|
162
|
+
/**
|
|
163
|
+
* any other task to run before
|
|
164
|
+
*/
|
|
165
|
+
preTask?: Task | TPreOrAfterTaskFunction;
|
|
166
|
+
/**
|
|
167
|
+
* any other task to run after
|
|
168
|
+
*/
|
|
169
|
+
afterTask?: Task | TPreOrAfterTaskFunction;
|
|
170
|
+
/**
|
|
171
|
+
* wether this task should run buffered
|
|
172
|
+
*/
|
|
173
|
+
buffered?: boolean;
|
|
174
|
+
/**
|
|
175
|
+
* the maximum buffer
|
|
176
|
+
*/
|
|
177
|
+
bufferMax?: number;
|
|
178
|
+
/**
|
|
179
|
+
* the execution delay, before the task is executed
|
|
180
|
+
* only makes sense when running in buffered mode
|
|
181
|
+
*/
|
|
182
|
+
execDelay?: number;
|
|
183
|
+
/**
|
|
184
|
+
* the name of the task
|
|
185
|
+
*/
|
|
186
|
+
name?: string;
|
|
187
|
+
}) {
|
|
188
|
+
this.taskFunction = optionsArg.taskFunction;
|
|
189
|
+
this.preTask = optionsArg.preTask;
|
|
190
|
+
this.afterTask = optionsArg.afterTask;
|
|
191
|
+
this.idle = !this.running;
|
|
192
|
+
this.buffered = optionsArg.buffered;
|
|
193
|
+
this.bufferMax = optionsArg.bufferMax;
|
|
194
|
+
this.execDelay = optionsArg.execDelay;
|
|
195
|
+
this.name = optionsArg.name;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* trigger the task. Will trigger buffered if this.buffered is true
|
|
200
|
+
*/
|
|
201
|
+
public trigger(x?: any): Promise<any> {
|
|
202
|
+
if (this.buffered) {
|
|
203
|
+
return this.triggerBuffered(x);
|
|
204
|
+
} else {
|
|
205
|
+
return this.triggerUnBuffered(x);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* trigger task unbuffered.
|
|
211
|
+
* will actually run the task, not considering any buffered limits.
|
|
212
|
+
*/
|
|
213
|
+
public triggerUnBuffered(x?: any): Promise<any> {
|
|
214
|
+
return Task.runTask(this, { x: x });
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* trigger task buffered.
|
|
219
|
+
* note: .trigger() also calls this function
|
|
220
|
+
*/
|
|
221
|
+
public triggerBuffered(x?: any): Promise<any> {
|
|
222
|
+
return this.bufferRunner.trigger(x);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
get state(): string {
|
|
226
|
+
return this._state;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
set state(stateArg: string) {
|
|
230
|
+
if (stateArg === 'locked') {
|
|
231
|
+
this._state = 'locked';
|
|
232
|
+
} else {
|
|
233
|
+
logger.log('error', `state type ${stateArg} could not be set`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// TaskChain chains tasks
|
|
2
|
+
// and extends Task
|
|
3
|
+
|
|
4
|
+
import * as plugins from './taskbuffer.plugins.js';
|
|
5
|
+
import { Task } from './taskbuffer.classes.task.js';
|
|
6
|
+
import { logger } from './taskbuffer.logging.js';
|
|
7
|
+
|
|
8
|
+
export class Taskchain extends Task {
|
|
9
|
+
taskArray: Task[];
|
|
10
|
+
constructor(optionsArg: {
|
|
11
|
+
taskArray: Task[];
|
|
12
|
+
name?: string;
|
|
13
|
+
log?: boolean;
|
|
14
|
+
buffered?: boolean;
|
|
15
|
+
bufferMax?: number;
|
|
16
|
+
}) {
|
|
17
|
+
const options = {
|
|
18
|
+
...{
|
|
19
|
+
name: 'unnamed Taskchain',
|
|
20
|
+
log: false,
|
|
21
|
+
},
|
|
22
|
+
...optionsArg,
|
|
23
|
+
...{
|
|
24
|
+
taskFunction: (x: any) => {
|
|
25
|
+
// this is the function that gets executed when TaskChain is triggered
|
|
26
|
+
const done = plugins.smartpromise.defer(); // this is the starting Deferred object
|
|
27
|
+
let taskCounter = 0; // counter for iterating async over the taskArray
|
|
28
|
+
const iterateTasks = (x: any) => {
|
|
29
|
+
if (typeof this.taskArray[taskCounter] !== 'undefined') {
|
|
30
|
+
console.log(this.name + ' running: Task' + this.taskArray[taskCounter].name);
|
|
31
|
+
this.taskArray[taskCounter].trigger(x).then((x) => {
|
|
32
|
+
logger.log('info', this.taskArray[taskCounter].name);
|
|
33
|
+
taskCounter++;
|
|
34
|
+
iterateTasks(x);
|
|
35
|
+
});
|
|
36
|
+
} else {
|
|
37
|
+
console.log('Taskchain "' + this.name + '" completed successfully');
|
|
38
|
+
done.resolve(x);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
iterateTasks(x);
|
|
42
|
+
return done.promise;
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
super(options);
|
|
47
|
+
this.taskArray = optionsArg.taskArray;
|
|
48
|
+
}
|
|
49
|
+
addTask(taskArg: Task) {
|
|
50
|
+
this.taskArray.push(taskArg);
|
|
51
|
+
}
|
|
52
|
+
removeTask(taskArg: Task) {
|
|
53
|
+
// TODO:
|
|
54
|
+
}
|
|
55
|
+
shiftTask() {
|
|
56
|
+
// TODO:
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as plugins from './taskbuffer.plugins.js';
|
|
2
|
+
|
|
3
|
+
import { Task, ITaskFunction } from './taskbuffer.classes.task.js';
|
|
4
|
+
|
|
5
|
+
export class TaskDebounced<T = unknown> extends Task {
|
|
6
|
+
private _debouncedTaskFunction: ITaskFunction;
|
|
7
|
+
private _observableIntake = new plugins.smartrx.ObservableIntake<T>();
|
|
8
|
+
|
|
9
|
+
constructor(optionsArg: {
|
|
10
|
+
name: string;
|
|
11
|
+
taskFunction: ITaskFunction;
|
|
12
|
+
debounceTimeInMillis: number;
|
|
13
|
+
}) {
|
|
14
|
+
super({
|
|
15
|
+
name: optionsArg.name,
|
|
16
|
+
taskFunction: async (x: T) => {
|
|
17
|
+
this._observableIntake.push(x);
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
this.taskFunction = optionsArg.taskFunction;
|
|
21
|
+
this._observableIntake.observable
|
|
22
|
+
.pipe(plugins.smartrx.rxjs.ops.debounceTime(optionsArg.debounceTimeInMillis))
|
|
23
|
+
.subscribe((x) => {
|
|
24
|
+
this.taskFunction(x);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import * as plugins from './taskbuffer.plugins.js';
|
|
2
|
+
import { Task } from './taskbuffer.classes.task.js';
|
|
3
|
+
import { AbstractDistributedCoordinator } from './taskbuffer.classes.distributedcoordinator.js';
|
|
4
|
+
|
|
5
|
+
export interface ICronJob {
|
|
6
|
+
cronString: string;
|
|
7
|
+
taskNameArg: string;
|
|
8
|
+
job: any;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ITaskManagerConstructorOptions {
|
|
12
|
+
distributedCoordinator?: AbstractDistributedCoordinator
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class TaskManager {
|
|
16
|
+
public randomId = plugins.isounique.uni();
|
|
17
|
+
public taskMap = new plugins.lik.ObjectMap<Task>();
|
|
18
|
+
private cronJobManager = new plugins.smarttime.CronManager();
|
|
19
|
+
|
|
20
|
+
public options: ITaskManagerConstructorOptions = {
|
|
21
|
+
distributedCoordinator: null
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
constructor(optionosArg: ITaskManagerConstructorOptions = {}) {
|
|
25
|
+
this.options = Object.assign(this.options, optionosArg);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* checks if a task is already present
|
|
30
|
+
* @param taskNameArg
|
|
31
|
+
*/
|
|
32
|
+
public getTaskByName(taskNameArg: string): Task {
|
|
33
|
+
return this.taskMap.findSync((itemArg) => {
|
|
34
|
+
return itemArg.name === taskNameArg;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* adds a Task to the TaskManager
|
|
40
|
+
* @param taskArg
|
|
41
|
+
*/
|
|
42
|
+
public addTask(taskArg: Task): void {
|
|
43
|
+
if (!taskArg.name) {
|
|
44
|
+
throw new Error('taskArg needs a name to be added to taskManager');
|
|
45
|
+
}
|
|
46
|
+
this.taskMap.add(taskArg);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* adds and schedules a task at once
|
|
51
|
+
* @param taskArg
|
|
52
|
+
* @param cronStringArg
|
|
53
|
+
*/
|
|
54
|
+
public addAndScheduleTask(taskArg: Task, cronStringArg: string) {
|
|
55
|
+
this.addTask(taskArg);
|
|
56
|
+
this.scheduleTaskByName(taskArg.name, cronStringArg);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* triggers a task in the TaskManagerByName
|
|
61
|
+
* @param taskNameArg
|
|
62
|
+
*/
|
|
63
|
+
public triggerTaskByName(taskNameArg: string): Promise<any> {
|
|
64
|
+
const taskToTrigger = this.getTaskByName(taskNameArg);
|
|
65
|
+
if (!taskToTrigger) {
|
|
66
|
+
throw new Error(`There is no task with the name of ${taskNameArg}`);
|
|
67
|
+
}
|
|
68
|
+
return taskToTrigger.trigger();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public async triggerTask(task: Task) {
|
|
72
|
+
return task.trigger();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* schedules the task by name
|
|
77
|
+
* @param taskNameArg
|
|
78
|
+
*/
|
|
79
|
+
public scheduleTaskByName(taskNameArg: string, cronStringArg: string) {
|
|
80
|
+
const taskToSchedule = this.getTaskByName(taskNameArg);
|
|
81
|
+
const cronJob = this.cronJobManager.addCronjob(cronStringArg, async (triggerTimeArg: number) => {
|
|
82
|
+
console.log(`taskbuffer schedule triggered task >>${taskToSchedule.name}<<`);
|
|
83
|
+
console.log(
|
|
84
|
+
`task >>${taskToSchedule.name}<< is ${
|
|
85
|
+
taskToSchedule.buffered
|
|
86
|
+
? `buffered with max ${taskToSchedule.bufferMax} buffered calls`
|
|
87
|
+
: `unbuffered`
|
|
88
|
+
}`
|
|
89
|
+
);
|
|
90
|
+
if (this.options.distributedCoordinator) {
|
|
91
|
+
console.log(`Found a distrubuted coordinator, performing distributed consultation.`);
|
|
92
|
+
const announcementResult = await this.options.distributedCoordinator.fireDistributedTaskRequest({
|
|
93
|
+
submitterRandomId: this.randomId,
|
|
94
|
+
status: 'requesting',
|
|
95
|
+
taskExecutionParallel: 1,
|
|
96
|
+
taskExecutionTime: triggerTimeArg,
|
|
97
|
+
taskExecutionTimeout: taskToSchedule.timeout,
|
|
98
|
+
taskName: taskToSchedule.name,
|
|
99
|
+
taskVersion: taskToSchedule.version,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
if (!announcementResult.shouldTrigger) {
|
|
103
|
+
console.log('distributed coordinator result: NOT EXECUTING')
|
|
104
|
+
return;
|
|
105
|
+
} else {
|
|
106
|
+
console.log('distributed coordinator result: CHOSEN AND EXECUTING')
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
await taskToSchedule.trigger();
|
|
110
|
+
});
|
|
111
|
+
taskToSchedule.cronJob = cronJob;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* deschedules a task by name
|
|
116
|
+
* @param taskNameArg
|
|
117
|
+
*/
|
|
118
|
+
public descheduleTaskByName(taskNameArg: string) {
|
|
119
|
+
const taskToDeSchedule = this.getTaskByName(taskNameArg);
|
|
120
|
+
if (taskToDeSchedule.cronJob) {
|
|
121
|
+
this.cronJobManager.removeCronjob(taskToDeSchedule.cronJob);
|
|
122
|
+
taskToDeSchedule.cronJob = null;
|
|
123
|
+
}
|
|
124
|
+
if (this.cronJobManager.cronjobs.isEmpty) {
|
|
125
|
+
this.cronJobManager.stop();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* deschedules a task
|
|
131
|
+
* @param task
|
|
132
|
+
*/
|
|
133
|
+
public async descheduleTask(task: Task) {
|
|
134
|
+
await this.descheduleTaskByName(task.name);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* returns all schedules of a specific task
|
|
138
|
+
* @param taskNameArg
|
|
139
|
+
*/
|
|
140
|
+
public getSchedulesForTaskName(taskNameArg: string) {}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* starts the taskmanager
|
|
144
|
+
*/
|
|
145
|
+
public start() {
|
|
146
|
+
this.cronJobManager.start();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* stops the taskmanager
|
|
151
|
+
*/
|
|
152
|
+
public stop() {
|
|
153
|
+
this.cronJobManager.stop();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as plugins from './taskbuffer.plugins.js';
|
|
2
|
+
|
|
3
|
+
import { Task, ITaskFunction } from './taskbuffer.classes.task.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* TaskOnce is run exactly once, no matter how often it is triggered
|
|
7
|
+
*/
|
|
8
|
+
export class TaskOnce extends Task {
|
|
9
|
+
hasTriggered: boolean = false;
|
|
10
|
+
constructor(optionsArg: { name?: string; taskFunction: ITaskFunction }) {
|
|
11
|
+
super({
|
|
12
|
+
name: optionsArg.name,
|
|
13
|
+
taskFunction: async () => {
|
|
14
|
+
if (!this.hasTriggered) {
|
|
15
|
+
this.hasTriggered = true;
|
|
16
|
+
await optionsArg.taskFunction();
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as plugins from './taskbuffer.plugins.js';
|
|
2
|
+
import { Task } from './taskbuffer.classes.task.js';
|
|
3
|
+
|
|
4
|
+
export class Taskparallel extends Task {
|
|
5
|
+
public taskArray: Task[];
|
|
6
|
+
constructor(optionsArg: { taskArray: Task[] }) {
|
|
7
|
+
const options = {
|
|
8
|
+
...optionsArg,
|
|
9
|
+
...{
|
|
10
|
+
taskFunction: () => {
|
|
11
|
+
const done = plugins.smartpromise.defer();
|
|
12
|
+
const promiseArray: Promise<any>[] = []; // stores promises of all tasks, since they run in parallel
|
|
13
|
+
this.taskArray.forEach(function (taskArg) {
|
|
14
|
+
promiseArray.push(taskArg.trigger());
|
|
15
|
+
});
|
|
16
|
+
Promise.all(promiseArray).then(done.resolve);
|
|
17
|
+
return done.promise;
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
super(options);
|
|
22
|
+
this.taskArray = optionsArg.taskArray;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as plugins from './taskbuffer.plugins.js';
|
|
2
|
+
|
|
3
|
+
import { Task } from './taskbuffer.classes.task.js';
|
|
4
|
+
|
|
5
|
+
export class TaskRunner {
|
|
6
|
+
public maxParrallelJobs: number = 1;
|
|
7
|
+
public status: 'stopped' | 'running' = 'stopped';
|
|
8
|
+
public runningTasks: plugins.lik.ObjectMap<Task> = new plugins.lik.ObjectMap<Task>();
|
|
9
|
+
public qeuedTasks: Task[] = [];
|
|
10
|
+
|
|
11
|
+
constructor() {
|
|
12
|
+
this.runningTasks.eventSubject.subscribe(async (eventArg) => {
|
|
13
|
+
this.checkExecution();
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* adds a task to the qeue
|
|
19
|
+
*/
|
|
20
|
+
public addTask(taskArg: Task) {
|
|
21
|
+
this.qeuedTasks.push(taskArg);
|
|
22
|
+
this.checkExecution();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* set amount of parallel tasks
|
|
27
|
+
* be careful, you might loose dependability of tasks
|
|
28
|
+
*/
|
|
29
|
+
public setMaxParallelJobs(maxParrallelJobsArg: number) {
|
|
30
|
+
this.maxParrallelJobs = maxParrallelJobsArg;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* starts the task queue
|
|
35
|
+
*/
|
|
36
|
+
public async start() {
|
|
37
|
+
this.status = 'running';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* checks wether execution is on point
|
|
42
|
+
*/
|
|
43
|
+
public async checkExecution() {
|
|
44
|
+
if (
|
|
45
|
+
this.runningTasks.getArray().length < this.maxParrallelJobs &&
|
|
46
|
+
this.status === 'running' &&
|
|
47
|
+
this.qeuedTasks.length > 0
|
|
48
|
+
) {
|
|
49
|
+
const nextJob = this.qeuedTasks.shift();
|
|
50
|
+
this.runningTasks.add(nextJob);
|
|
51
|
+
await nextJob.trigger();
|
|
52
|
+
this.runningTasks.remove(nextJob);
|
|
53
|
+
this.checkExecution();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* stops the task queue
|
|
59
|
+
*/
|
|
60
|
+
public async stop() {
|
|
61
|
+
this.status = 'stopped';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as isounique from '@pushrocks/isounique';
|
|
2
|
+
import * as lik from '@pushrocks/lik';
|
|
3
|
+
import * as smartlog from '@pushrocks/smartlog';
|
|
4
|
+
import * as smartpromise from '@pushrocks/smartpromise';
|
|
5
|
+
import * as smartdelay from '@pushrocks/smartdelay';
|
|
6
|
+
import * as smartrx from '@pushrocks/smartrx';
|
|
7
|
+
import * as smarttime from '@pushrocks/smarttime';
|
|
8
|
+
|
|
9
|
+
export { isounique, lik, smartlog, smartpromise, smartdelay, smartrx, smarttime };
|