@twin.org/background-task-scheduler 0.0.2-next.9 → 0.0.3-next.2
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/es/index.js +6 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/ITaskSchedulerConfig.js +4 -0
- package/dist/es/models/ITaskSchedulerConfig.js.map +1 -0
- package/dist/es/models/ITaskSchedulerConstructorOptions.js +2 -0
- package/dist/es/models/ITaskSchedulerConstructorOptions.js.map +1 -0
- package/dist/{esm/index.mjs → es/taskSchedulerService.js} +15 -11
- package/dist/es/taskSchedulerService.js.map +1 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/models/ITaskSchedulerConstructorOptions.d.ts +1 -1
- package/dist/types/taskSchedulerService.d.ts +7 -3
- package/docs/changelog.md +42 -0
- package/docs/reference/classes/TaskSchedulerService.md +20 -8
- package/package.json +6 -8
- package/dist/cjs/index.cjs +0 -209
package/dist/es/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
export * from "./models/ITaskSchedulerConfig.js";
|
|
4
|
+
export * from "./models/ITaskSchedulerConstructorOptions.js";
|
|
5
|
+
export * from "./taskSchedulerService.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,kCAAkC,CAAC;AACjD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,2BAA2B,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./models/ITaskSchedulerConfig.js\";\nexport * from \"./models/ITaskSchedulerConstructorOptions.js\";\nexport * from \"./taskSchedulerService.js\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITaskSchedulerConfig.js","sourceRoot":"","sources":["../../../src/models/ITaskSchedulerConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Interface for the task scheduler configuration.\n */\nexport interface ITaskSchedulerConfig {\n\t/**\n\t * The interval between checks for running tasks, defaults to 1 minute since that is the resolution of the tasks.\n\t * @default 60000\n\t */\n\toverrideInterval?: number;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITaskSchedulerConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/ITaskSchedulerConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITaskSchedulerConfig } from \"./ITaskSchedulerConfig.js\";\n\n/**\n * Options for the task scheduler constructor.\n */\nexport interface ITaskSchedulerConstructorOptions {\n\t/**\n\t * The logging component type.\n\t * @default logging\n\t */\n\tloggingComponentType?: string;\n\n\t/**\n\t * The configuration for the task scheduler.\n\t */\n\tconfig?: ITaskSchedulerConfig;\n}\n"]}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { ComponentFactory, Is
|
|
2
|
-
|
|
1
|
+
import { BaseError, ComponentFactory, Is } from "@twin.org/core";
|
|
3
2
|
/**
|
|
4
3
|
* Class for scheduling tasks.
|
|
5
4
|
*/
|
|
6
|
-
class TaskSchedulerService {
|
|
5
|
+
export class TaskSchedulerService {
|
|
7
6
|
/**
|
|
8
7
|
* Runtime name for the class.
|
|
9
8
|
*/
|
|
@@ -37,13 +36,19 @@ class TaskSchedulerService {
|
|
|
37
36
|
this._tasks = {};
|
|
38
37
|
this._tickInterval = options?.config?.overrideInterval ?? 60 * 1000; // Default to 1 minute
|
|
39
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Returns the class name of the component.
|
|
41
|
+
* @returns The class name of the component.
|
|
42
|
+
*/
|
|
43
|
+
className() {
|
|
44
|
+
return TaskSchedulerService.CLASS_NAME;
|
|
45
|
+
}
|
|
40
46
|
/**
|
|
41
47
|
* The component needs to be stopped when the node is closed.
|
|
42
|
-
* @param nodeIdentity The identity of the node stopping the component.
|
|
43
48
|
* @param nodeLoggingComponentType The node logging component type.
|
|
44
49
|
* @returns Nothing.
|
|
45
50
|
*/
|
|
46
|
-
async stop(
|
|
51
|
+
async stop(nodeLoggingComponentType) {
|
|
47
52
|
this.stopTimer();
|
|
48
53
|
}
|
|
49
54
|
/**
|
|
@@ -63,7 +68,7 @@ class TaskSchedulerService {
|
|
|
63
68
|
})),
|
|
64
69
|
taskCallback
|
|
65
70
|
};
|
|
66
|
-
this._logging?.log({
|
|
71
|
+
await this._logging?.log({
|
|
67
72
|
level: "info",
|
|
68
73
|
source: TaskSchedulerService.CLASS_NAME,
|
|
69
74
|
ts: Date.now(),
|
|
@@ -81,7 +86,7 @@ class TaskSchedulerService {
|
|
|
81
86
|
*/
|
|
82
87
|
async removeTask(taskId) {
|
|
83
88
|
if (!Is.empty(this._tasks[taskId])) {
|
|
84
|
-
this._logging?.log({
|
|
89
|
+
await this._logging?.log({
|
|
85
90
|
level: "info",
|
|
86
91
|
source: TaskSchedulerService.CLASS_NAME,
|
|
87
92
|
ts: Date.now(),
|
|
@@ -163,7 +168,7 @@ class TaskSchedulerService {
|
|
|
163
168
|
const task = this._tasks[taskId];
|
|
164
169
|
for (const taskTime of task.times) {
|
|
165
170
|
if (!Is.empty(taskTime.nextTriggerTime) && taskTime.nextTriggerTime <= now) {
|
|
166
|
-
this._logging?.log({
|
|
171
|
+
await this._logging?.log({
|
|
167
172
|
level: "info",
|
|
168
173
|
source: TaskSchedulerService.CLASS_NAME,
|
|
169
174
|
ts: Date.now(),
|
|
@@ -177,7 +182,7 @@ class TaskSchedulerService {
|
|
|
177
182
|
await task.taskCallback();
|
|
178
183
|
}
|
|
179
184
|
catch (error) {
|
|
180
|
-
this._logging?.log({
|
|
185
|
+
await this._logging?.log({
|
|
181
186
|
level: "error",
|
|
182
187
|
source: TaskSchedulerService.CLASS_NAME,
|
|
183
188
|
ts: Date.now(),
|
|
@@ -203,5 +208,4 @@ class TaskSchedulerService {
|
|
|
203
208
|
}
|
|
204
209
|
}
|
|
205
210
|
}
|
|
206
|
-
|
|
207
|
-
export { TaskSchedulerService };
|
|
211
|
+
//# sourceMappingURL=taskSchedulerService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskSchedulerService.js","sourceRoot":"","sources":["../../src/taskSchedulerService.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAKjE;;GAEG;AACH,MAAM,OAAO,oBAAoB;IAChC;;OAEG;IACI,MAAM,CAAU,UAAU,0BAA0C;IAE3E;;;OAGG;IACc,QAAQ,CAAqB;IAE9C;;;OAGG;IACc,aAAa,CAAS;IAEvC;;;OAGG;IACc,MAAM,CAKrB;IAEF;;;OAGG;IACK,MAAM,CAAkB;IAEhC;;;OAGG;IACH,YAAY,OAA0C;QACrD,IAAI,CAAC,QAAQ,GAAG,gBAAgB,CAAC,WAAW,CAAC,OAAO,EAAE,oBAAoB,IAAI,SAAS,CAAC,CAAC;QACzF,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,OAAO,EAAE,MAAM,EAAE,gBAAgB,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,sBAAsB;IAC5F,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,oBAAoB,CAAC,UAAU,CAAC;IACxC,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,IAAI,CAAC,wBAAiC;QAClD,IAAI,CAAC,SAAS,EAAE,CAAC;IAClB,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,OAAO,CACnB,MAAc,EACd,KAA2B,EAC3B,YAAiC;QAEjC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG;YACrB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACzB,GAAG,IAAI;gBACP,eAAe,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC;oBAC9C,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC;oBACrC,CAAC,CAAC,IAAI,CAAC,eAAe;aACvB,CAAC,CAAC;YACH,YAAY;SACZ,CAAC;QAEF,MAAM,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC;YACxB,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,oBAAoB,CAAC,UAAU;YACvC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,OAAO,EAAE,WAAW;YACpB,IAAI,EAAE;gBACL,EAAE,EAAE,MAAM;aACV;SACD,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,UAAU,CAAC,MAAc;QACrC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC;gBACxB,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,oBAAoB,CAAC,UAAU;gBACvC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,OAAO,EAAE,aAAa;gBACtB,IAAI,EAAE;oBACL,EAAE,EAAE,MAAM;iBACV;aACD,CAAC,CAAC;YAEH,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAE3B,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3C,IAAI,CAAC,SAAS,EAAE,CAAC;YAClB,CAAC;QACF,CAAC;IACF,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,SAAS;QACrB,MAAM,SAAS,GAAuB;YACrC,KAAK,EAAE,EAAE;SACT,CAAC;QACF,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAClC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC;QACrD,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;;;;OAKG;IACK,wBAAwB,CAAC,IAAwB;QACxD,IAAI,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;QAE3C,IAAI,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC;YAC/B,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAClC,eAAe,IAAI,IAAI,CAAC,YAAY,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAC5D,CAAC;QAED,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YACnC,eAAe,IAAI,IAAI,CAAC,aAAa,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QACxD,CAAC;QAED,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;YACrC,eAAe,IAAI,IAAI,CAAC,eAAe,GAAG,EAAE,GAAG,IAAI,CAAC;QACrD,CAAC;QAED,OAAO,eAAe,CAAC;IACxB,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,UAAU;QACvB,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,sDAAsD;YACtD,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACnC,iDAAiD;YACjD,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACzF,CAAC;IACF,CAAC;IAED;;;OAGG;IACK,SAAS;QAChB,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACzB,CAAC;IACF,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,qBAAqB;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAEjC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACnC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,QAAQ,CAAC,eAAe,IAAI,GAAG,EAAE,CAAC;oBAC5E,MAAM,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC;wBACxB,KAAK,EAAE,MAAM;wBACb,MAAM,EAAE,oBAAoB,CAAC,UAAU;wBACvC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;wBACd,OAAO,EAAE,eAAe;wBACxB,IAAI,EAAE;4BACL,EAAE,EAAE,MAAM;4BACV,IAAI,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE;yBACtD;qBACD,CAAC,CAAC;oBAEH,IAAI,CAAC;wBACJ,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;oBAC3B,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBAChB,MAAM,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC;4BACxB,KAAK,EAAE,OAAO;4BACd,MAAM,EAAE,oBAAoB,CAAC,UAAU;4BACvC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;4BACd,OAAO,EAAE,YAAY;4BACrB,IAAI,EAAE;gCACL,EAAE,EAAE,MAAM;6BACV;4BACD,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC;yBACjC,CAAC,CAAC;oBACJ,CAAC;oBAED,oEAAoE;oBACpE,IACC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC;wBAC/B,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC;wBAChC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,EACjC,CAAC;wBACF,QAAQ,CAAC,eAAe,GAAG,SAAS,CAAC;oBACtC,CAAC;yBAAM,CAAC;wBACP,4EAA4E;wBAC5E,QAAQ,CAAC,eAAe,GAAG,IAAI,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC;oBACpE,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {\n\tIScheduledTaskInfo,\n\tIScheduledTaskTime,\n\tITaskSchedulerComponent\n} from \"@twin.org/background-task-models\";\nimport { BaseError, ComponentFactory, Is } from \"@twin.org/core\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { ITaskSchedulerConstructorOptions } from \"./models/ITaskSchedulerConstructorOptions.js\";\n\n/**\n * Class for scheduling tasks.\n */\nexport class TaskSchedulerService implements ITaskSchedulerComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<TaskSchedulerService>();\n\n\t/**\n\t * The logger for the task service.\n\t * @internal\n\t */\n\tprivate readonly _logging?: ILoggingComponent;\n\n\t/**\n\t * The interval in milliseconds at which the tasks are checked.\n\t * @internal\n\t */\n\tprivate readonly _tickInterval: number;\n\n\t/**\n\t * The tasks that are scheduled.\n\t * @internal\n\t */\n\tprivate readonly _tasks: {\n\t\t[id: string]: {\n\t\t\ttimes: IScheduledTaskTime[];\n\t\t\ttaskCallback: () => Promise<void>;\n\t\t};\n\t};\n\n\t/**\n\t * The timer for running scheduled tasks.\n\t * @internal\n\t */\n\tprivate _timer?: NodeJS.Timeout;\n\n\t/**\n\t * Create a new instance of TaskSchedulerComponent.\n\t * @param options The options for the scheduler.\n\t */\n\tconstructor(options?: ITaskSchedulerConstructorOptions) {\n\t\tthis._logging = ComponentFactory.getIfExists(options?.loggingComponentType ?? \"logging\");\n\t\tthis._tasks = {};\n\t\tthis._tickInterval = options?.config?.overrideInterval ?? 60 * 1000; // Default to 1 minute\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn TaskSchedulerService.CLASS_NAME;\n\t}\n\n\t/**\n\t * The component needs to be stopped when the node is closed.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async stop(nodeLoggingComponentType?: string): Promise<void> {\n\t\tthis.stopTimer();\n\t}\n\n\t/**\n\t * Add a task to the scheduler.\n\t * @param taskId The id of the task to add.\n\t * @param times The times at which the task should be scheduled.\n\t * @param taskCallback The callback to execute when the task is scheduled.\n\t * @returns Nothing.\n\t */\n\tpublic async addTask(\n\t\ttaskId: string,\n\t\ttimes: IScheduledTaskTime[],\n\t\ttaskCallback: () => Promise<void>\n\t): Promise<void> {\n\t\tthis._tasks[taskId] = {\n\t\t\ttimes: times.map(time => ({\n\t\t\t\t...time,\n\t\t\t\tnextTriggerTime: Is.empty(time.nextTriggerTime)\n\t\t\t\t\t? this.calculateNextTriggerTime(time)\n\t\t\t\t\t: time.nextTriggerTime\n\t\t\t})),\n\t\t\ttaskCallback\n\t\t};\n\n\t\tawait this._logging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: TaskSchedulerService.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"taskAdded\",\n\t\t\tdata: {\n\t\t\t\tid: taskId\n\t\t\t}\n\t\t});\n\n\t\tawait this.startTimer();\n\t}\n\n\t/**\n\t * Remove a task from the scheduler.\n\t * @param taskId The id of the task to remove.\n\t * @returns Nothing.\n\t */\n\tpublic async removeTask(taskId: string): Promise<void> {\n\t\tif (!Is.empty(this._tasks[taskId])) {\n\t\t\tawait this._logging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: TaskSchedulerService.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"taskRemoved\",\n\t\t\t\tdata: {\n\t\t\t\t\tid: taskId\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tdelete this._tasks[taskId];\n\n\t\t\tif (Object.keys(this._tasks).length === 0) {\n\t\t\t\tthis.stopTimer();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get the information about the tasks.\n\t * @returns The tasks information.\n\t */\n\tpublic async tasksInfo(): Promise<IScheduledTaskInfo> {\n\t\tconst tasksInfo: IScheduledTaskInfo = {\n\t\t\ttasks: {}\n\t\t};\n\t\tfor (const taskId in this._tasks) {\n\t\t\ttasksInfo.tasks[taskId] = this._tasks[taskId].times;\n\t\t}\n\t\treturn tasksInfo;\n\t}\n\n\t/**\n\t * Calculate the next run time for a task based on its scheduled times.\n\t * @param time The times at which the task should be scheduled.\n\t * @returns The update time with the next run.\n\t * @internal\n\t */\n\tprivate calculateNextTriggerTime(time: IScheduledTaskTime): number {\n\t\tlet nextTriggerTime = time.nextTriggerTime;\n\n\t\tif (Is.empty(nextTriggerTime)) {\n\t\t\tnextTriggerTime = Date.now();\n\t\t}\n\n\t\tif (!Is.empty(time.intervalDays)) {\n\t\t\tnextTriggerTime += time.intervalDays * 24 * 60 * 60 * 1000;\n\t\t}\n\n\t\tif (!Is.empty(time.intervalHours)) {\n\t\t\tnextTriggerTime += time.intervalHours * 60 * 60 * 1000;\n\t\t}\n\n\t\tif (!Is.empty(time.intervalMinutes)) {\n\t\t\tnextTriggerTime += time.intervalMinutes * 60 * 1000;\n\t\t}\n\n\t\treturn nextTriggerTime;\n\t}\n\n\t/**\n\t * Start the timer for running scheduled tasks.\n\t * @internal\n\t */\n\tprivate async startTimer(): Promise<void> {\n\t\tif (Is.empty(this._timer)) {\n\t\t\t// Trigger immediately to catch up on any missed tasks\n\t\t\tawait this.triggerScheduledTasks();\n\t\t\t// Set the timer to run at the specified interval\n\t\t\tthis._timer = setInterval(async () => this.triggerScheduledTasks(), this._tickInterval);\n\t\t}\n\t}\n\n\t/**\n\t * Stop the timer for running scheduled tasks.\n\t * @internal\n\t */\n\tprivate stopTimer(): void {\n\t\tif (!Is.empty(this._timer)) {\n\t\t\tclearInterval(this._timer);\n\t\t\tthis._timer = undefined;\n\t\t}\n\t}\n\n\t/**\n\t * Trigger scheduled tasks based on their next run times.\n\t * @internal\n\t */\n\tprivate async triggerScheduledTasks(): Promise<void> {\n\t\tconst now = Date.now();\n\n\t\tfor (const taskId in this._tasks) {\n\t\t\tconst task = this._tasks[taskId];\n\n\t\t\tfor (const taskTime of task.times) {\n\t\t\t\tif (!Is.empty(taskTime.nextTriggerTime) && taskTime.nextTriggerTime <= now) {\n\t\t\t\t\tawait this._logging?.log({\n\t\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\t\tsource: TaskSchedulerService.CLASS_NAME,\n\t\t\t\t\t\tts: Date.now(),\n\t\t\t\t\t\tmessage: \"taskTriggered\",\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tid: taskId,\n\t\t\t\t\t\t\ttime: new Date(taskTime.nextTriggerTime).toISOString()\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait task.taskCallback();\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tawait this._logging?.log({\n\t\t\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\t\t\tsource: TaskSchedulerService.CLASS_NAME,\n\t\t\t\t\t\t\tts: Date.now(),\n\t\t\t\t\t\t\tmessage: \"taskFailed\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tid: taskId\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\terror: BaseError.fromError(error)\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the intervals are empty, we do not recalculate a next run time\n\t\t\t\t\tif (\n\t\t\t\t\t\tIs.empty(taskTime.intervalDays) &&\n\t\t\t\t\t\tIs.empty(taskTime.intervalHours) &&\n\t\t\t\t\t\tIs.empty(taskTime.intervalMinutes)\n\t\t\t\t\t) {\n\t\t\t\t\t\ttaskTime.nextTriggerTime = undefined;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Recalculate the next run time based on the current time and the intervals\n\t\t\t\t\t\ttaskTime.nextTriggerTime = this.calculateNextTriggerTime(taskTime);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from "./models/ITaskSchedulerConfig";
|
|
2
|
-
export * from "./models/ITaskSchedulerConstructorOptions";
|
|
3
|
-
export * from "./taskSchedulerService";
|
|
1
|
+
export * from "./models/ITaskSchedulerConfig.js";
|
|
2
|
+
export * from "./models/ITaskSchedulerConstructorOptions.js";
|
|
3
|
+
export * from "./taskSchedulerService.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IScheduledTaskInfo, IScheduledTaskTime, ITaskSchedulerComponent } from "@twin.org/background-task-models";
|
|
2
|
-
import type { ITaskSchedulerConstructorOptions } from "./models/ITaskSchedulerConstructorOptions";
|
|
2
|
+
import type { ITaskSchedulerConstructorOptions } from "./models/ITaskSchedulerConstructorOptions.js";
|
|
3
3
|
/**
|
|
4
4
|
* Class for scheduling tasks.
|
|
5
5
|
*/
|
|
@@ -13,13 +13,17 @@ export declare class TaskSchedulerService implements ITaskSchedulerComponent {
|
|
|
13
13
|
* @param options The options for the scheduler.
|
|
14
14
|
*/
|
|
15
15
|
constructor(options?: ITaskSchedulerConstructorOptions);
|
|
16
|
+
/**
|
|
17
|
+
* Returns the class name of the component.
|
|
18
|
+
* @returns The class name of the component.
|
|
19
|
+
*/
|
|
20
|
+
className(): string;
|
|
16
21
|
/**
|
|
17
22
|
* The component needs to be stopped when the node is closed.
|
|
18
|
-
* @param nodeIdentity The identity of the node stopping the component.
|
|
19
23
|
* @param nodeLoggingComponentType The node logging component type.
|
|
20
24
|
* @returns Nothing.
|
|
21
25
|
*/
|
|
22
|
-
stop(
|
|
26
|
+
stop(nodeLoggingComponentType?: string): Promise<void>;
|
|
23
27
|
/**
|
|
24
28
|
* Add a task to the scheduler.
|
|
25
29
|
* @param taskId The id of the task to add.
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.2](https://github.com/twinfoundation/background-task/compare/background-task-scheduler-v0.0.3-next.1...background-task-scheduler-v0.0.3-next.2) (2025-11-28)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Miscellaneous Chores
|
|
7
|
+
|
|
8
|
+
* **background-task-scheduler:** Synchronize repo versions
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/background-task-models bumped from 0.0.3-next.1 to 0.0.3-next.2
|
|
16
|
+
|
|
17
|
+
## [0.0.3-next.1](https://github.com/twinfoundation/background-task/compare/background-task-scheduler-v0.0.3-next.0...background-task-scheduler-v0.0.3-next.1) (2025-11-11)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* add context id features ([#29](https://github.com/twinfoundation/background-task/issues/29)) ([46ede49](https://github.com/twinfoundation/background-task/commit/46ede49a51a4955fe1530e645a66f0073db9a1fd))
|
|
23
|
+
* add task scheduler ([754d973](https://github.com/twinfoundation/background-task/commit/754d973e7c8483e5e54e887c157661867d5a0375))
|
|
24
|
+
* add validate-locales ([968cbf9](https://github.com/twinfoundation/background-task/commit/968cbf966fffb5060305e8b221fecc0b6c8105b9))
|
|
25
|
+
* background tasks immediately trigger ([a0a847b](https://github.com/twinfoundation/background-task/commit/a0a847ba9686adcd0460e810540959f87dcaeab1))
|
|
26
|
+
* eslint migration to flat config ([6c9136c](https://github.com/twinfoundation/background-task/commit/6c9136c37bccdbbd109892d1503660aab7080d49))
|
|
27
|
+
* remove unused parameters ([1028b3c](https://github.com/twinfoundation/background-task/commit/1028b3cc147c25da22a8ba8d7207acfb34f89cdb))
|
|
28
|
+
* rename task scheduler component ([2f8aa59](https://github.com/twinfoundation/background-task/commit/2f8aa59c069055ff020a3c0c149601f20c656022))
|
|
29
|
+
* rename task scheduler component to service ([f097a98](https://github.com/twinfoundation/background-task/commit/f097a988c9ee0795aa55d74deda616365ec4ffb1))
|
|
30
|
+
* update framework core ([a068098](https://github.com/twinfoundation/background-task/commit/a0680983d7923a1bfb980a67879019bb870ccc5d))
|
|
31
|
+
* update IComponent signatures ([e1a79bc](https://github.com/twinfoundation/background-task/commit/e1a79bc4dd813435c56e376f231a4b4ecd2276bf))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Bug Fixes
|
|
35
|
+
|
|
36
|
+
* models import ([c830b0d](https://github.com/twinfoundation/background-task/commit/c830b0da4deb06f8aeca6fec8988be4da877e73b))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Dependencies
|
|
40
|
+
|
|
41
|
+
* The following workspace dependencies were updated
|
|
42
|
+
* dependencies
|
|
43
|
+
* @twin.org/background-task-models bumped from 0.0.3-next.0 to 0.0.3-next.1
|
|
44
|
+
|
|
3
45
|
## [0.0.2-next.9](https://github.com/twinfoundation/background-task/compare/background-task-scheduler-v0.0.2-next.8...background-task-scheduler-v0.0.2-next.9) (2025-10-09)
|
|
4
46
|
|
|
5
47
|
|
|
@@ -36,26 +36,38 @@ Runtime name for the class.
|
|
|
36
36
|
|
|
37
37
|
## Methods
|
|
38
38
|
|
|
39
|
+
### className()
|
|
40
|
+
|
|
41
|
+
> **className**(): `string`
|
|
42
|
+
|
|
43
|
+
Returns the class name of the component.
|
|
44
|
+
|
|
45
|
+
#### Returns
|
|
46
|
+
|
|
47
|
+
`string`
|
|
48
|
+
|
|
49
|
+
The class name of the component.
|
|
50
|
+
|
|
51
|
+
#### Implementation of
|
|
52
|
+
|
|
53
|
+
`ITaskSchedulerComponent.className`
|
|
54
|
+
|
|
55
|
+
***
|
|
56
|
+
|
|
39
57
|
### stop()
|
|
40
58
|
|
|
41
|
-
> **stop**(`
|
|
59
|
+
> **stop**(`nodeLoggingComponentType?`): `Promise`\<`void`\>
|
|
42
60
|
|
|
43
61
|
The component needs to be stopped when the node is closed.
|
|
44
62
|
|
|
45
63
|
#### Parameters
|
|
46
64
|
|
|
47
|
-
#####
|
|
65
|
+
##### nodeLoggingComponentType?
|
|
48
66
|
|
|
49
67
|
`string`
|
|
50
68
|
|
|
51
|
-
The identity of the node stopping the component.
|
|
52
|
-
|
|
53
|
-
##### nodeLoggingComponentType
|
|
54
|
-
|
|
55
69
|
The node logging component type.
|
|
56
70
|
|
|
57
|
-
`undefined` | `string`
|
|
58
|
-
|
|
59
71
|
#### Returns
|
|
60
72
|
|
|
61
73
|
`Promise`\<`void`\>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/background-task-scheduler",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3-next.2",
|
|
4
4
|
"description": "Background task scheduler",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,25 +14,23 @@
|
|
|
14
14
|
"node": ">=20.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@twin.org/background-task-models": "0.0.
|
|
17
|
+
"@twin.org/background-task-models": "0.0.3-next.2",
|
|
18
18
|
"@twin.org/core": "next",
|
|
19
19
|
"@twin.org/logging-models": "next",
|
|
20
20
|
"@twin.org/nameof": "next"
|
|
21
21
|
},
|
|
22
|
-
"main": "./dist/
|
|
23
|
-
"module": "./dist/esm/index.mjs",
|
|
22
|
+
"main": "./dist/es/index.js",
|
|
24
23
|
"types": "./dist/types/index.d.ts",
|
|
25
24
|
"exports": {
|
|
26
25
|
".": {
|
|
27
26
|
"types": "./dist/types/index.d.ts",
|
|
28
|
-
"
|
|
29
|
-
"
|
|
27
|
+
"import": "./dist/es/index.js",
|
|
28
|
+
"default": "./dist/es/index.js"
|
|
30
29
|
},
|
|
31
30
|
"./locales/*.json": "./locales/*.json"
|
|
32
31
|
},
|
|
33
32
|
"files": [
|
|
34
|
-
"dist/
|
|
35
|
-
"dist/esm",
|
|
33
|
+
"dist/es",
|
|
36
34
|
"dist/types",
|
|
37
35
|
"locales",
|
|
38
36
|
"docs"
|
package/dist/cjs/index.cjs
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var core = require('@twin.org/core');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Class for scheduling tasks.
|
|
7
|
-
*/
|
|
8
|
-
class TaskSchedulerService {
|
|
9
|
-
/**
|
|
10
|
-
* Runtime name for the class.
|
|
11
|
-
*/
|
|
12
|
-
static CLASS_NAME = "TaskSchedulerService";
|
|
13
|
-
/**
|
|
14
|
-
* The logger for the task service.
|
|
15
|
-
* @internal
|
|
16
|
-
*/
|
|
17
|
-
_logging;
|
|
18
|
-
/**
|
|
19
|
-
* The interval in milliseconds at which the tasks are checked.
|
|
20
|
-
* @internal
|
|
21
|
-
*/
|
|
22
|
-
_tickInterval;
|
|
23
|
-
/**
|
|
24
|
-
* The tasks that are scheduled.
|
|
25
|
-
* @internal
|
|
26
|
-
*/
|
|
27
|
-
_tasks;
|
|
28
|
-
/**
|
|
29
|
-
* The timer for running scheduled tasks.
|
|
30
|
-
* @internal
|
|
31
|
-
*/
|
|
32
|
-
_timer;
|
|
33
|
-
/**
|
|
34
|
-
* Create a new instance of TaskSchedulerComponent.
|
|
35
|
-
* @param options The options for the scheduler.
|
|
36
|
-
*/
|
|
37
|
-
constructor(options) {
|
|
38
|
-
this._logging = core.ComponentFactory.getIfExists(options?.loggingComponentType ?? "logging");
|
|
39
|
-
this._tasks = {};
|
|
40
|
-
this._tickInterval = options?.config?.overrideInterval ?? 60 * 1000; // Default to 1 minute
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* The component needs to be stopped when the node is closed.
|
|
44
|
-
* @param nodeIdentity The identity of the node stopping the component.
|
|
45
|
-
* @param nodeLoggingComponentType The node logging component type.
|
|
46
|
-
* @returns Nothing.
|
|
47
|
-
*/
|
|
48
|
-
async stop(nodeIdentity, nodeLoggingComponentType) {
|
|
49
|
-
this.stopTimer();
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Add a task to the scheduler.
|
|
53
|
-
* @param taskId The id of the task to add.
|
|
54
|
-
* @param times The times at which the task should be scheduled.
|
|
55
|
-
* @param taskCallback The callback to execute when the task is scheduled.
|
|
56
|
-
* @returns Nothing.
|
|
57
|
-
*/
|
|
58
|
-
async addTask(taskId, times, taskCallback) {
|
|
59
|
-
this._tasks[taskId] = {
|
|
60
|
-
times: times.map(time => ({
|
|
61
|
-
...time,
|
|
62
|
-
nextTriggerTime: core.Is.empty(time.nextTriggerTime)
|
|
63
|
-
? this.calculateNextTriggerTime(time)
|
|
64
|
-
: time.nextTriggerTime
|
|
65
|
-
})),
|
|
66
|
-
taskCallback
|
|
67
|
-
};
|
|
68
|
-
this._logging?.log({
|
|
69
|
-
level: "info",
|
|
70
|
-
source: TaskSchedulerService.CLASS_NAME,
|
|
71
|
-
ts: Date.now(),
|
|
72
|
-
message: "taskAdded",
|
|
73
|
-
data: {
|
|
74
|
-
id: taskId
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
await this.startTimer();
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Remove a task from the scheduler.
|
|
81
|
-
* @param taskId The id of the task to remove.
|
|
82
|
-
* @returns Nothing.
|
|
83
|
-
*/
|
|
84
|
-
async removeTask(taskId) {
|
|
85
|
-
if (!core.Is.empty(this._tasks[taskId])) {
|
|
86
|
-
this._logging?.log({
|
|
87
|
-
level: "info",
|
|
88
|
-
source: TaskSchedulerService.CLASS_NAME,
|
|
89
|
-
ts: Date.now(),
|
|
90
|
-
message: "taskRemoved",
|
|
91
|
-
data: {
|
|
92
|
-
id: taskId
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
delete this._tasks[taskId];
|
|
96
|
-
if (Object.keys(this._tasks).length === 0) {
|
|
97
|
-
this.stopTimer();
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Get the information about the tasks.
|
|
103
|
-
* @returns The tasks information.
|
|
104
|
-
*/
|
|
105
|
-
async tasksInfo() {
|
|
106
|
-
const tasksInfo = {
|
|
107
|
-
tasks: {}
|
|
108
|
-
};
|
|
109
|
-
for (const taskId in this._tasks) {
|
|
110
|
-
tasksInfo.tasks[taskId] = this._tasks[taskId].times;
|
|
111
|
-
}
|
|
112
|
-
return tasksInfo;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Calculate the next run time for a task based on its scheduled times.
|
|
116
|
-
* @param time The times at which the task should be scheduled.
|
|
117
|
-
* @returns The update time with the next run.
|
|
118
|
-
* @internal
|
|
119
|
-
*/
|
|
120
|
-
calculateNextTriggerTime(time) {
|
|
121
|
-
let nextTriggerTime = time.nextTriggerTime;
|
|
122
|
-
if (core.Is.empty(nextTriggerTime)) {
|
|
123
|
-
nextTriggerTime = Date.now();
|
|
124
|
-
}
|
|
125
|
-
if (!core.Is.empty(time.intervalDays)) {
|
|
126
|
-
nextTriggerTime += time.intervalDays * 24 * 60 * 60 * 1000;
|
|
127
|
-
}
|
|
128
|
-
if (!core.Is.empty(time.intervalHours)) {
|
|
129
|
-
nextTriggerTime += time.intervalHours * 60 * 60 * 1000;
|
|
130
|
-
}
|
|
131
|
-
if (!core.Is.empty(time.intervalMinutes)) {
|
|
132
|
-
nextTriggerTime += time.intervalMinutes * 60 * 1000;
|
|
133
|
-
}
|
|
134
|
-
return nextTriggerTime;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Start the timer for running scheduled tasks.
|
|
138
|
-
* @internal
|
|
139
|
-
*/
|
|
140
|
-
async startTimer() {
|
|
141
|
-
if (core.Is.empty(this._timer)) {
|
|
142
|
-
// Trigger immediately to catch up on any missed tasks
|
|
143
|
-
await this.triggerScheduledTasks();
|
|
144
|
-
// Set the timer to run at the specified interval
|
|
145
|
-
this._timer = setInterval(async () => this.triggerScheduledTasks(), this._tickInterval);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Stop the timer for running scheduled tasks.
|
|
150
|
-
* @internal
|
|
151
|
-
*/
|
|
152
|
-
stopTimer() {
|
|
153
|
-
if (!core.Is.empty(this._timer)) {
|
|
154
|
-
clearInterval(this._timer);
|
|
155
|
-
this._timer = undefined;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Trigger scheduled tasks based on their next run times.
|
|
160
|
-
* @internal
|
|
161
|
-
*/
|
|
162
|
-
async triggerScheduledTasks() {
|
|
163
|
-
const now = Date.now();
|
|
164
|
-
for (const taskId in this._tasks) {
|
|
165
|
-
const task = this._tasks[taskId];
|
|
166
|
-
for (const taskTime of task.times) {
|
|
167
|
-
if (!core.Is.empty(taskTime.nextTriggerTime) && taskTime.nextTriggerTime <= now) {
|
|
168
|
-
this._logging?.log({
|
|
169
|
-
level: "info",
|
|
170
|
-
source: TaskSchedulerService.CLASS_NAME,
|
|
171
|
-
ts: Date.now(),
|
|
172
|
-
message: "taskTriggered",
|
|
173
|
-
data: {
|
|
174
|
-
id: taskId,
|
|
175
|
-
time: new Date(taskTime.nextTriggerTime).toISOString()
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
try {
|
|
179
|
-
await task.taskCallback();
|
|
180
|
-
}
|
|
181
|
-
catch (error) {
|
|
182
|
-
this._logging?.log({
|
|
183
|
-
level: "error",
|
|
184
|
-
source: TaskSchedulerService.CLASS_NAME,
|
|
185
|
-
ts: Date.now(),
|
|
186
|
-
message: "taskFailed",
|
|
187
|
-
data: {
|
|
188
|
-
id: taskId
|
|
189
|
-
},
|
|
190
|
-
error: core.BaseError.fromError(error)
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
// If the intervals are empty, we do not recalculate a next run time
|
|
194
|
-
if (core.Is.empty(taskTime.intervalDays) &&
|
|
195
|
-
core.Is.empty(taskTime.intervalHours) &&
|
|
196
|
-
core.Is.empty(taskTime.intervalMinutes)) {
|
|
197
|
-
taskTime.nextTriggerTime = undefined;
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
// Recalculate the next run time based on the current time and the intervals
|
|
201
|
-
taskTime.nextTriggerTime = this.calculateNextTriggerTime(taskTime);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
exports.TaskSchedulerService = TaskSchedulerService;
|