@twin.org/background-task-scheduler 0.0.3-next.1 → 0.0.3-next.11
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/README.md +1 -1
- package/dist/es/entities/scheduledTask.js +29 -0
- package/dist/es/entities/scheduledTask.js.map +1 -0
- package/dist/es/index.js +2 -0
- package/dist/es/index.js.map +1 -1
- package/dist/es/models/ITaskSchedulerConfig.js.map +1 -1
- package/dist/es/models/ITaskSchedulerConstructorOptions.js.map +1 -1
- package/dist/es/schema.js +11 -0
- package/dist/es/schema.js.map +1 -0
- package/dist/es/taskSchedulerService.js +86 -14
- package/dist/es/taskSchedulerService.js.map +1 -1
- package/dist/types/entities/scheduledTask.d.ts +13 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/models/ITaskSchedulerConfig.d.ts +6 -1
- package/dist/types/models/ITaskSchedulerConstructorOptions.d.ts +5 -0
- package/dist/types/schema.d.ts +4 -0
- package/docs/changelog.md +201 -43
- package/docs/examples.md +95 -1
- package/docs/reference/classes/ScheduledTask.md +29 -0
- package/docs/reference/classes/TaskSchedulerService.md +6 -6
- package/docs/reference/functions/initSchema.md +9 -0
- package/docs/reference/index.md +5 -0
- package/docs/reference/interfaces/ITaskSchedulerConfig.md +16 -2
- package/docs/reference/interfaces/ITaskSchedulerConstructorOptions.md +18 -4
- package/locales/en.json +5 -0
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { entity, property } from "@twin.org/entity";
|
|
4
|
+
/**
|
|
5
|
+
* Class defining a scheduled task.
|
|
6
|
+
*/
|
|
7
|
+
let ScheduledTask = class ScheduledTask {
|
|
8
|
+
/**
|
|
9
|
+
* The id.
|
|
10
|
+
*/
|
|
11
|
+
id;
|
|
12
|
+
/**
|
|
13
|
+
* The last run time of the task, if undefined waiting for next run.
|
|
14
|
+
*/
|
|
15
|
+
lastRunTime;
|
|
16
|
+
};
|
|
17
|
+
__decorate([
|
|
18
|
+
property({ type: "string", isPrimary: true }),
|
|
19
|
+
__metadata("design:type", String)
|
|
20
|
+
], ScheduledTask.prototype, "id", void 0);
|
|
21
|
+
__decorate([
|
|
22
|
+
property({ type: "integer", optional: true, format: "uint64" }),
|
|
23
|
+
__metadata("design:type", Number)
|
|
24
|
+
], ScheduledTask.prototype, "lastRunTime", void 0);
|
|
25
|
+
ScheduledTask = __decorate([
|
|
26
|
+
entity()
|
|
27
|
+
], ScheduledTask);
|
|
28
|
+
export { ScheduledTask };
|
|
29
|
+
//# sourceMappingURL=scheduledTask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduledTask.js","sourceRoot":"","sources":["../../../src/entities/scheduledTask.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;GAEG;AAEI,IAAM,aAAa,GAAnB,MAAM,aAAa;IACzB;;OAEG;IAEI,EAAE,CAAU;IAEnB;;OAEG;IAEI,WAAW,CAAU;CAC5B,CAAA;AAPO;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;;yCAC3B;AAMZ;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;;kDACpC;AAXhB,aAAa;IADzB,MAAM,EAAE;GACI,aAAa,CAYzB","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { entity, property } from \"@twin.org/entity\";\n\n/**\n * Class defining a scheduled task.\n */\n@entity()\nexport class ScheduledTask {\n\t/**\n\t * The id.\n\t */\n\t@property({ type: \"string\", isPrimary: true })\n\tpublic id!: string;\n\n\t/**\n\t * The last run time of the task, if undefined waiting for next run.\n\t */\n\t@property({ type: \"integer\", optional: true, format: \"uint64\" })\n\tpublic lastRunTime?: number;\n}\n"]}
|
package/dist/es/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Copyright 2024 IOTA Stiftung.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
export * from "./entities/scheduledTask.js";
|
|
3
4
|
export * from "./models/ITaskSchedulerConfig.js";
|
|
4
5
|
export * from "./models/ITaskSchedulerConstructorOptions.js";
|
|
6
|
+
export * from "./schema.js";
|
|
5
7
|
export * from "./taskSchedulerService.js";
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
package/dist/es/index.js.map
CHANGED
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./entities/scheduledTask.js\";\nexport * from \"./models/ITaskSchedulerConfig.js\";\nexport * from \"./models/ITaskSchedulerConstructorOptions.js\";\nexport * from \"./schema.js\";\nexport * from \"./taskSchedulerService.js\";\n"]}
|
|
@@ -1 +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\
|
|
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\tintervalMs?: number;\n\n\t/**\n\t * The time in milliseconds after which a task that is still marked as running is considered stalled and can be run again.\n\t * @default 300000\n\t */\n\tstalledTaskTimeoutMs?: number;\n}\n"]}
|
|
@@ -1 +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
|
+
{"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 scheduled task entity storage connector type.\n\t * @default scheduled-task\n\t */\n\tscheduledTaskEntityStorageType?: string;\n\n\t/**\n\t * The configuration for the task scheduler.\n\t */\n\tconfig?: ITaskSchedulerConfig;\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { EntitySchemaFactory, EntitySchemaHelper } from "@twin.org/entity";
|
|
4
|
+
import { ScheduledTask } from "./entities/scheduledTask.js";
|
|
5
|
+
/**
|
|
6
|
+
* Initialize the schema for the scheduled task service entity storage.
|
|
7
|
+
*/
|
|
8
|
+
export function initSchema() {
|
|
9
|
+
EntitySchemaFactory.register("ScheduledTask", () => EntitySchemaHelper.getSchema(ScheduledTask));
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3E,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D;;GAEG;AACH,MAAM,UAAU,UAAU;IACzB,mBAAmB,CAAC,QAAQ,kBAA0B,GAAG,EAAE,CAC1D,kBAAkB,CAAC,SAAS,CAAC,aAAa,CAAC,CAC3C,CAAC;AACH,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { EntitySchemaFactory, EntitySchemaHelper } from \"@twin.org/entity\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { ScheduledTask } from \"./entities/scheduledTask.js\";\n\n/**\n * Initialize the schema for the scheduled task service entity storage.\n */\nexport function initSchema(): void {\n\tEntitySchemaFactory.register(nameof<ScheduledTask>(), () =>\n\t\tEntitySchemaHelper.getSchema(ScheduledTask)\n\t);\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseError, ComponentFactory, Is } from "@twin.org/core";
|
|
2
|
+
import { EntityStorageConnectorFactory } from "@twin.org/entity-storage-models";
|
|
2
3
|
/**
|
|
3
4
|
* Class for scheduling tasks.
|
|
4
5
|
*/
|
|
@@ -12,16 +13,31 @@ export class TaskSchedulerService {
|
|
|
12
13
|
* @internal
|
|
13
14
|
*/
|
|
14
15
|
_logging;
|
|
16
|
+
/**
|
|
17
|
+
* The entity storage for the scheduled tasks.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
_scheduledTaskEntityStorageConnector;
|
|
15
21
|
/**
|
|
16
22
|
* The interval in milliseconds at which the tasks are checked.
|
|
17
23
|
* @internal
|
|
18
24
|
*/
|
|
19
|
-
|
|
25
|
+
_tickIntervalMs;
|
|
26
|
+
/**
|
|
27
|
+
* The timeout in milliseconds after which an in-progress task is considered stalled.
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
_stalledTaskTimeoutMs;
|
|
20
31
|
/**
|
|
21
32
|
* The tasks that are scheduled.
|
|
22
33
|
* @internal
|
|
23
34
|
*/
|
|
24
35
|
_tasks;
|
|
36
|
+
/**
|
|
37
|
+
* The tasks currently running in this scheduler instance.
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
_runningTasks;
|
|
25
41
|
/**
|
|
26
42
|
* The timer for running scheduled tasks.
|
|
27
43
|
* @internal
|
|
@@ -32,9 +48,12 @@ export class TaskSchedulerService {
|
|
|
32
48
|
* @param options The options for the scheduler.
|
|
33
49
|
*/
|
|
34
50
|
constructor(options) {
|
|
51
|
+
this._scheduledTaskEntityStorageConnector = EntityStorageConnectorFactory.get(options?.scheduledTaskEntityStorageType ?? "scheduled-task");
|
|
35
52
|
this._logging = ComponentFactory.getIfExists(options?.loggingComponentType ?? "logging");
|
|
36
53
|
this._tasks = {};
|
|
37
|
-
this.
|
|
54
|
+
this._runningTasks = [];
|
|
55
|
+
this._tickIntervalMs = options?.config?.intervalMs ?? 60 * 1000; // 1 minute
|
|
56
|
+
this._stalledTaskTimeoutMs = options?.config?.stalledTaskTimeoutMs ?? 5 * 60 * 1000; // 5 minutes
|
|
38
57
|
}
|
|
39
58
|
/**
|
|
40
59
|
* Returns the class name of the component.
|
|
@@ -50,6 +69,15 @@ export class TaskSchedulerService {
|
|
|
50
69
|
*/
|
|
51
70
|
async stop(nodeLoggingComponentType) {
|
|
52
71
|
this.stopTimer();
|
|
72
|
+
// If we had any running tasks, we reset their last run time to allow them to be
|
|
73
|
+
// triggered by other components
|
|
74
|
+
for (const taskId of this._runningTasks) {
|
|
75
|
+
await this._scheduledTaskEntityStorageConnector.set({
|
|
76
|
+
id: taskId,
|
|
77
|
+
lastRunTime: undefined
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
this._runningTasks = [];
|
|
53
81
|
}
|
|
54
82
|
/**
|
|
55
83
|
* Add a task to the scheduler.
|
|
@@ -145,7 +173,7 @@ export class TaskSchedulerService {
|
|
|
145
173
|
// Trigger immediately to catch up on any missed tasks
|
|
146
174
|
await this.triggerScheduledTasks();
|
|
147
175
|
// Set the timer to run at the specified interval
|
|
148
|
-
this._timer = setInterval(async () => this.triggerScheduledTasks(), this.
|
|
176
|
+
this._timer = setInterval(async () => this.triggerScheduledTasks(), this._tickIntervalMs);
|
|
149
177
|
}
|
|
150
178
|
}
|
|
151
179
|
/**
|
|
@@ -168,18 +196,48 @@ export class TaskSchedulerService {
|
|
|
168
196
|
const task = this._tasks[taskId];
|
|
169
197
|
for (const taskTime of task.times) {
|
|
170
198
|
if (!Is.empty(taskTime.nextTriggerTime) && taskTime.nextTriggerTime <= now) {
|
|
171
|
-
|
|
172
|
-
level: "info",
|
|
173
|
-
source: TaskSchedulerService.CLASS_NAME,
|
|
174
|
-
ts: Date.now(),
|
|
175
|
-
message: "taskTriggered",
|
|
176
|
-
data: {
|
|
177
|
-
id: taskId,
|
|
178
|
-
time: new Date(taskTime.nextTriggerTime).toISOString()
|
|
179
|
-
}
|
|
180
|
-
});
|
|
199
|
+
let taskStarted = false;
|
|
181
200
|
try {
|
|
182
|
-
await
|
|
201
|
+
const scheduledTask = await this._scheduledTaskEntityStorageConnector.get(taskId);
|
|
202
|
+
const lastRunTime = scheduledTask?.lastRunTime;
|
|
203
|
+
const taskInProgress = !Is.empty(lastRunTime);
|
|
204
|
+
const taskStalled = taskInProgress && now - lastRunTime >= this._stalledTaskTimeoutMs;
|
|
205
|
+
if (taskStalled) {
|
|
206
|
+
await this._logging?.log({
|
|
207
|
+
level: "warn",
|
|
208
|
+
source: TaskSchedulerService.CLASS_NAME,
|
|
209
|
+
ts: Date.now(),
|
|
210
|
+
message: "taskStalled",
|
|
211
|
+
data: {
|
|
212
|
+
id: taskId,
|
|
213
|
+
lastRunTime,
|
|
214
|
+
stalledForMs: now - (lastRunTime ?? now),
|
|
215
|
+
stalledTaskTimeoutMs: this._stalledTaskTimeoutMs
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (!taskInProgress || taskStalled) {
|
|
220
|
+
await this._logging?.log({
|
|
221
|
+
level: "info",
|
|
222
|
+
source: TaskSchedulerService.CLASS_NAME,
|
|
223
|
+
ts: Date.now(),
|
|
224
|
+
message: "taskTriggered",
|
|
225
|
+
data: {
|
|
226
|
+
id: taskId,
|
|
227
|
+
time: new Date(taskTime.nextTriggerTime).toISOString()
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
// Update the last run time of the task to prevent multiple triggers in case of long running tasks
|
|
231
|
+
await this._scheduledTaskEntityStorageConnector.set({
|
|
232
|
+
id: taskId,
|
|
233
|
+
lastRunTime: Date.now()
|
|
234
|
+
});
|
|
235
|
+
if (!this._runningTasks.includes(taskId)) {
|
|
236
|
+
this._runningTasks.push(taskId);
|
|
237
|
+
}
|
|
238
|
+
taskStarted = true;
|
|
239
|
+
await task.taskCallback();
|
|
240
|
+
}
|
|
183
241
|
}
|
|
184
242
|
catch (error) {
|
|
185
243
|
await this._logging?.log({
|
|
@@ -193,6 +251,20 @@ export class TaskSchedulerService {
|
|
|
193
251
|
error: BaseError.fromError(error)
|
|
194
252
|
});
|
|
195
253
|
}
|
|
254
|
+
finally {
|
|
255
|
+
if (taskStarted) {
|
|
256
|
+
// Reset the last run time to allow future triggers, even if the task callback fails
|
|
257
|
+
await this._scheduledTaskEntityStorageConnector.set({
|
|
258
|
+
id: taskId,
|
|
259
|
+
lastRunTime: undefined
|
|
260
|
+
});
|
|
261
|
+
// Remove the task from the running tasks list
|
|
262
|
+
const index = this._runningTasks.indexOf(taskId);
|
|
263
|
+
if (index >= 0) {
|
|
264
|
+
this._runningTasks.splice(index, 1);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
196
268
|
// If the intervals are empty, we do not recalculate a next run time
|
|
197
269
|
if (Is.empty(taskTime.intervalDays) &&
|
|
198
270
|
Is.empty(taskTime.intervalHours) &&
|
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"file":"taskSchedulerService.js","sourceRoot":"","sources":["../../src/taskSchedulerService.ts"],"names":[],"mappings":"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","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 {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { ScheduledTask } from \"./entities/scheduledTask.js\";\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 entity storage for the scheduled tasks.\n\t * @internal\n\t */\n\tprivate readonly _scheduledTaskEntityStorageConnector: IEntityStorageConnector<ScheduledTask>;\n\n\t/**\n\t * The interval in milliseconds at which the tasks are checked.\n\t * @internal\n\t */\n\tprivate readonly _tickIntervalMs: number;\n\n\t/**\n\t * The timeout in milliseconds after which an in-progress task is considered stalled.\n\t * @internal\n\t */\n\tprivate readonly _stalledTaskTimeoutMs: 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 tasks currently running in this scheduler instance.\n\t * @internal\n\t */\n\tprivate _runningTasks: string[];\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._scheduledTaskEntityStorageConnector = EntityStorageConnectorFactory.get(\n\t\t\toptions?.scheduledTaskEntityStorageType ?? \"scheduled-task\"\n\t\t);\n\t\tthis._logging = ComponentFactory.getIfExists(options?.loggingComponentType ?? \"logging\");\n\t\tthis._tasks = {};\n\t\tthis._runningTasks = [];\n\t\tthis._tickIntervalMs = options?.config?.intervalMs ?? 60 * 1000; // 1 minute\n\t\tthis._stalledTaskTimeoutMs = options?.config?.stalledTaskTimeoutMs ?? 5 * 60 * 1000; // 5 minutes\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\n\t\t// If we had any running tasks, we reset their last run time to allow them to be\n\t\t// triggered by other components\n\t\tfor (const taskId of this._runningTasks) {\n\t\t\tawait this._scheduledTaskEntityStorageConnector.set({\n\t\t\t\tid: taskId,\n\t\t\t\tlastRunTime: undefined\n\t\t\t});\n\t\t}\n\t\tthis._runningTasks = [];\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._tickIntervalMs);\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\tlet taskStarted = false;\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst scheduledTask = await this._scheduledTaskEntityStorageConnector.get(taskId);\n\t\t\t\t\t\tconst lastRunTime = scheduledTask?.lastRunTime;\n\t\t\t\t\t\tconst taskInProgress = !Is.empty(lastRunTime);\n\t\t\t\t\t\tconst taskStalled = taskInProgress && now - lastRunTime >= this._stalledTaskTimeoutMs;\n\n\t\t\t\t\t\tif (taskStalled) {\n\t\t\t\t\t\t\tawait this._logging?.log({\n\t\t\t\t\t\t\t\tlevel: \"warn\",\n\t\t\t\t\t\t\t\tsource: TaskSchedulerService.CLASS_NAME,\n\t\t\t\t\t\t\t\tts: Date.now(),\n\t\t\t\t\t\t\t\tmessage: \"taskStalled\",\n\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\tid: taskId,\n\t\t\t\t\t\t\t\t\tlastRunTime,\n\t\t\t\t\t\t\t\t\tstalledForMs: now - (lastRunTime ?? now),\n\t\t\t\t\t\t\t\t\tstalledTaskTimeoutMs: this._stalledTaskTimeoutMs\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!taskInProgress || taskStalled) {\n\t\t\t\t\t\t\tawait this._logging?.log({\n\t\t\t\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\t\t\t\tsource: TaskSchedulerService.CLASS_NAME,\n\t\t\t\t\t\t\t\tts: Date.now(),\n\t\t\t\t\t\t\t\tmessage: \"taskTriggered\",\n\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\tid: taskId,\n\t\t\t\t\t\t\t\t\ttime: new Date(taskTime.nextTriggerTime).toISOString()\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// Update the last run time of the task to prevent multiple triggers in case of long running tasks\n\t\t\t\t\t\t\tawait this._scheduledTaskEntityStorageConnector.set({\n\t\t\t\t\t\t\t\tid: taskId,\n\t\t\t\t\t\t\t\tlastRunTime: Date.now()\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (!this._runningTasks.includes(taskId)) {\n\t\t\t\t\t\t\t\tthis._runningTasks.push(taskId);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ttaskStarted = true;\n\t\t\t\t\t\t\tawait task.taskCallback();\n\t\t\t\t\t\t}\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} finally {\n\t\t\t\t\t\tif (taskStarted) {\n\t\t\t\t\t\t\t// Reset the last run time to allow future triggers, even if the task callback fails\n\t\t\t\t\t\t\tawait this._scheduledTaskEntityStorageConnector.set({\n\t\t\t\t\t\t\t\tid: taskId,\n\t\t\t\t\t\t\t\tlastRunTime: undefined\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// Remove the task from the running tasks list\n\t\t\t\t\t\t\tconst index = this._runningTasks.indexOf(taskId);\n\t\t\t\t\t\t\tif (index >= 0) {\n\t\t\t\t\t\t\t\tthis._runningTasks.splice(index, 1);\n\t\t\t\t\t\t\t}\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
|
@@ -6,5 +6,10 @@ export interface ITaskSchedulerConfig {
|
|
|
6
6
|
* The interval between checks for running tasks, defaults to 1 minute since that is the resolution of the tasks.
|
|
7
7
|
* @default 60000
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
intervalMs?: number;
|
|
10
|
+
/**
|
|
11
|
+
* The time in milliseconds after which a task that is still marked as running is considered stalled and can be run again.
|
|
12
|
+
* @default 300000
|
|
13
|
+
*/
|
|
14
|
+
stalledTaskTimeoutMs?: number;
|
|
10
15
|
}
|
|
@@ -8,6 +8,11 @@ export interface ITaskSchedulerConstructorOptions {
|
|
|
8
8
|
* @default logging
|
|
9
9
|
*/
|
|
10
10
|
loggingComponentType?: string;
|
|
11
|
+
/**
|
|
12
|
+
* The scheduled task entity storage connector type.
|
|
13
|
+
* @default scheduled-task
|
|
14
|
+
*/
|
|
15
|
+
scheduledTaskEntityStorageType?: string;
|
|
11
16
|
/**
|
|
12
17
|
* The configuration for the task scheduler.
|
|
13
18
|
*/
|
package/docs/changelog.md
CHANGED
|
@@ -1,25 +1,183 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [0.0.3-next.
|
|
3
|
+
## [0.0.3-next.11](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.3-next.10...background-task-scheduler-v0.0.3-next.11) (2026-06-10)
|
|
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.10 to 0.0.3-next.11
|
|
16
|
+
|
|
17
|
+
## [0.0.3-next.10](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.3-next.9...background-task-scheduler-v0.0.3-next.10) (2026-06-09)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Miscellaneous Chores
|
|
21
|
+
|
|
22
|
+
* **background-task-scheduler:** Synchronize repo versions
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Dependencies
|
|
26
|
+
|
|
27
|
+
* The following workspace dependencies were updated
|
|
28
|
+
* dependencies
|
|
29
|
+
* @twin.org/background-task-models bumped from 0.0.3-next.9 to 0.0.3-next.10
|
|
30
|
+
|
|
31
|
+
## [0.0.3-next.9](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.3-next.8...background-task-scheduler-v0.0.3-next.9) (2026-06-08)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Features
|
|
35
|
+
|
|
36
|
+
* add context id features ([#29](https://github.com/iotaledger/twin-background-task/issues/29)) ([46ede49](https://github.com/iotaledger/twin-background-task/commit/46ede49a51a4955fe1530e645a66f0073db9a1fd))
|
|
37
|
+
* add task scheduler ([754d973](https://github.com/iotaledger/twin-background-task/commit/754d973e7c8483e5e54e887c157661867d5a0375))
|
|
38
|
+
* add validate-locales ([968cbf9](https://github.com/iotaledger/twin-background-task/commit/968cbf966fffb5060305e8b221fecc0b6c8105b9))
|
|
39
|
+
* background tasks immediately trigger ([a0a847b](https://github.com/iotaledger/twin-background-task/commit/a0a847ba9686adcd0460e810540959f87dcaeab1))
|
|
40
|
+
* eslint migration to flat config ([6c9136c](https://github.com/iotaledger/twin-background-task/commit/6c9136c37bccdbbd109892d1503660aab7080d49))
|
|
41
|
+
* multi-instance lock ([#39](https://github.com/iotaledger/twin-background-task/issues/39)) ([7dcd434](https://github.com/iotaledger/twin-background-task/commit/7dcd434da5e3d1645b6fcd19ed34be4e628e50de))
|
|
42
|
+
* remove unused parameters ([1028b3c](https://github.com/iotaledger/twin-background-task/commit/1028b3cc147c25da22a8ba8d7207acfb34f89cdb))
|
|
43
|
+
* rename task scheduler component ([2f8aa59](https://github.com/iotaledger/twin-background-task/commit/2f8aa59c069055ff020a3c0c149601f20c656022))
|
|
44
|
+
* rename task scheduler component to service ([f097a98](https://github.com/iotaledger/twin-background-task/commit/f097a988c9ee0795aa55d74deda616365ec4ffb1))
|
|
45
|
+
* typescript 6 update ([e3f2727](https://github.com/iotaledger/twin-background-task/commit/e3f272783e0de7cf4d31f3e84a8e6f5ff633961b))
|
|
46
|
+
* update dependencies ([0867e02](https://github.com/iotaledger/twin-background-task/commit/0867e02fc3c034f8e8cf5918ac6cc4e6b5ca0c93))
|
|
47
|
+
* update framework core ([a068098](https://github.com/iotaledger/twin-background-task/commit/a0680983d7923a1bfb980a67879019bb870ccc5d))
|
|
48
|
+
* update IComponent signatures ([e1a79bc](https://github.com/iotaledger/twin-background-task/commit/e1a79bc4dd813435c56e376f231a4b4ecd2276bf))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
### Bug Fixes
|
|
52
|
+
|
|
53
|
+
* models import ([c830b0d](https://github.com/iotaledger/twin-background-task/commit/c830b0da4deb06f8aeca6fec8988be4da877e73b))
|
|
54
|
+
* restore task context in background task state-change callbacks ([#46](https://github.com/iotaledger/twin-background-task/issues/46)) ([d4f9f3b](https://github.com/iotaledger/twin-background-task/commit/d4f9f3bb57f8fb83c62024f9a385c81e2d511920))
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
### Dependencies
|
|
58
|
+
|
|
59
|
+
* The following workspace dependencies were updated
|
|
60
|
+
* dependencies
|
|
61
|
+
* @twin.org/background-task-models bumped from 0.0.3-next.8 to 0.0.3-next.9
|
|
62
|
+
|
|
63
|
+
## [0.0.3-next.8](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.3-next.7...background-task-scheduler-v0.0.3-next.8) (2026-06-08)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
### Bug Fixes
|
|
67
|
+
|
|
68
|
+
* restore task context in background task state-change callbacks ([#46](https://github.com/iotaledger/twin-background-task/issues/46)) ([d4f9f3b](https://github.com/iotaledger/twin-background-task/commit/d4f9f3bb57f8fb83c62024f9a385c81e2d511920))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
### Dependencies
|
|
72
|
+
|
|
73
|
+
* The following workspace dependencies were updated
|
|
74
|
+
* dependencies
|
|
75
|
+
* @twin.org/background-task-models bumped from 0.0.3-next.7 to 0.0.3-next.8
|
|
76
|
+
|
|
77
|
+
## [0.0.3-next.7](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.3-next.6...background-task-scheduler-v0.0.3-next.7) (2026-05-20)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
### Features
|
|
81
|
+
|
|
82
|
+
* update dependencies ([0867e02](https://github.com/iotaledger/twin-background-task/commit/0867e02fc3c034f8e8cf5918ac6cc4e6b5ca0c93))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
### Dependencies
|
|
86
|
+
|
|
87
|
+
* The following workspace dependencies were updated
|
|
88
|
+
* dependencies
|
|
89
|
+
* @twin.org/background-task-models bumped from 0.0.3-next.6 to 0.0.3-next.7
|
|
90
|
+
|
|
91
|
+
## [0.0.3-next.6](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.3-next.5...background-task-scheduler-v0.0.3-next.6) (2026-05-11)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
### Features
|
|
95
|
+
|
|
96
|
+
* typescript 6 update ([e3f2727](https://github.com/iotaledger/twin-background-task/commit/e3f272783e0de7cf4d31f3e84a8e6f5ff633961b))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
### Dependencies
|
|
100
|
+
|
|
101
|
+
* The following workspace dependencies were updated
|
|
102
|
+
* dependencies
|
|
103
|
+
* @twin.org/background-task-models bumped from 0.0.3-next.5 to 0.0.3-next.6
|
|
104
|
+
|
|
105
|
+
## [0.0.3-next.5](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.3-next.4...background-task-scheduler-v0.0.3-next.5) (2026-04-10)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
### Miscellaneous Chores
|
|
109
|
+
|
|
110
|
+
* **background-task-scheduler:** Synchronize repo versions
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
### Dependencies
|
|
114
|
+
|
|
115
|
+
* The following workspace dependencies were updated
|
|
116
|
+
* dependencies
|
|
117
|
+
* @twin.org/background-task-models bumped from 0.0.3-next.4 to 0.0.3-next.5
|
|
118
|
+
|
|
119
|
+
## [0.0.3-next.4](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.3-next.3...background-task-scheduler-v0.0.3-next.4) (2026-02-23)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
### Features
|
|
123
|
+
|
|
124
|
+
* multi-instance lock ([#39](https://github.com/iotaledger/twin-background-task/issues/39)) ([7dcd434](https://github.com/iotaledger/twin-background-task/commit/7dcd434da5e3d1645b6fcd19ed34be4e628e50de))
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
### Dependencies
|
|
128
|
+
|
|
129
|
+
* The following workspace dependencies were updated
|
|
130
|
+
* dependencies
|
|
131
|
+
* @twin.org/background-task-models bumped from 0.0.3-next.3 to 0.0.3-next.4
|
|
132
|
+
|
|
133
|
+
## [0.0.3-next.3](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.3-next.2...background-task-scheduler-v0.0.3-next.3) (2026-01-07)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
### Miscellaneous Chores
|
|
137
|
+
|
|
138
|
+
* **background-task-scheduler:** Synchronize repo versions
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
### Dependencies
|
|
142
|
+
|
|
143
|
+
* The following workspace dependencies were updated
|
|
144
|
+
* dependencies
|
|
145
|
+
* @twin.org/background-task-models bumped from 0.0.3-next.2 to 0.0.3-next.3
|
|
146
|
+
|
|
147
|
+
## [0.0.3-next.2](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.3-next.1...background-task-scheduler-v0.0.3-next.2) (2025-11-28)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
### Miscellaneous Chores
|
|
151
|
+
|
|
152
|
+
* **background-task-scheduler:** Synchronize repo versions
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
### Dependencies
|
|
156
|
+
|
|
157
|
+
* The following workspace dependencies were updated
|
|
158
|
+
* dependencies
|
|
159
|
+
* @twin.org/background-task-models bumped from 0.0.3-next.1 to 0.0.3-next.2
|
|
160
|
+
|
|
161
|
+
## [0.0.3-next.1](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.3-next.0...background-task-scheduler-v0.0.3-next.1) (2025-11-11)
|
|
4
162
|
|
|
5
163
|
|
|
6
164
|
### Features
|
|
7
165
|
|
|
8
|
-
* add context id features ([#29](https://github.com/
|
|
9
|
-
* add task scheduler ([754d973](https://github.com/
|
|
10
|
-
* add validate-locales ([968cbf9](https://github.com/
|
|
11
|
-
* background tasks immediately trigger ([a0a847b](https://github.com/
|
|
12
|
-
* eslint migration to flat config ([6c9136c](https://github.com/
|
|
13
|
-
* remove unused parameters ([1028b3c](https://github.com/
|
|
14
|
-
* rename task scheduler component ([2f8aa59](https://github.com/
|
|
15
|
-
* rename task scheduler component to service ([f097a98](https://github.com/
|
|
16
|
-
* update framework core ([a068098](https://github.com/
|
|
17
|
-
* update IComponent signatures ([e1a79bc](https://github.com/
|
|
166
|
+
* add context id features ([#29](https://github.com/iotaledger/twin-background-task/issues/29)) ([46ede49](https://github.com/iotaledger/twin-background-task/commit/46ede49a51a4955fe1530e645a66f0073db9a1fd))
|
|
167
|
+
* add task scheduler ([754d973](https://github.com/iotaledger/twin-background-task/commit/754d973e7c8483e5e54e887c157661867d5a0375))
|
|
168
|
+
* add validate-locales ([968cbf9](https://github.com/iotaledger/twin-background-task/commit/968cbf966fffb5060305e8b221fecc0b6c8105b9))
|
|
169
|
+
* background tasks immediately trigger ([a0a847b](https://github.com/iotaledger/twin-background-task/commit/a0a847ba9686adcd0460e810540959f87dcaeab1))
|
|
170
|
+
* eslint migration to flat config ([6c9136c](https://github.com/iotaledger/twin-background-task/commit/6c9136c37bccdbbd109892d1503660aab7080d49))
|
|
171
|
+
* remove unused parameters ([1028b3c](https://github.com/iotaledger/twin-background-task/commit/1028b3cc147c25da22a8ba8d7207acfb34f89cdb))
|
|
172
|
+
* rename task scheduler component ([2f8aa59](https://github.com/iotaledger/twin-background-task/commit/2f8aa59c069055ff020a3c0c149601f20c656022))
|
|
173
|
+
* rename task scheduler component to service ([f097a98](https://github.com/iotaledger/twin-background-task/commit/f097a988c9ee0795aa55d74deda616365ec4ffb1))
|
|
174
|
+
* update framework core ([a068098](https://github.com/iotaledger/twin-background-task/commit/a0680983d7923a1bfb980a67879019bb870ccc5d))
|
|
175
|
+
* update IComponent signatures ([e1a79bc](https://github.com/iotaledger/twin-background-task/commit/e1a79bc4dd813435c56e376f231a4b4ecd2276bf))
|
|
18
176
|
|
|
19
177
|
|
|
20
178
|
### Bug Fixes
|
|
21
179
|
|
|
22
|
-
* models import ([c830b0d](https://github.com/
|
|
180
|
+
* models import ([c830b0d](https://github.com/iotaledger/twin-background-task/commit/c830b0da4deb06f8aeca6fec8988be4da877e73b))
|
|
23
181
|
|
|
24
182
|
|
|
25
183
|
### Dependencies
|
|
@@ -28,12 +186,12 @@
|
|
|
28
186
|
* dependencies
|
|
29
187
|
* @twin.org/background-task-models bumped from 0.0.3-next.0 to 0.0.3-next.1
|
|
30
188
|
|
|
31
|
-
## [0.0.2-next.9](https://github.com/
|
|
189
|
+
## [0.0.2-next.9](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.2-next.8...background-task-scheduler-v0.0.2-next.9) (2025-10-09)
|
|
32
190
|
|
|
33
191
|
|
|
34
192
|
### Features
|
|
35
193
|
|
|
36
|
-
* add validate-locales ([968cbf9](https://github.com/
|
|
194
|
+
* add validate-locales ([968cbf9](https://github.com/iotaledger/twin-background-task/commit/968cbf966fffb5060305e8b221fecc0b6c8105b9))
|
|
37
195
|
|
|
38
196
|
|
|
39
197
|
### Dependencies
|
|
@@ -42,12 +200,12 @@
|
|
|
42
200
|
* dependencies
|
|
43
201
|
* @twin.org/background-task-models bumped from 0.0.2-next.8 to 0.0.2-next.9
|
|
44
202
|
|
|
45
|
-
## [0.0.2-next.8](https://github.com/
|
|
203
|
+
## [0.0.2-next.8](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.2-next.7...background-task-scheduler-v0.0.2-next.8) (2025-09-29)
|
|
46
204
|
|
|
47
205
|
|
|
48
206
|
### Features
|
|
49
207
|
|
|
50
|
-
* update IComponent signatures ([e1a79bc](https://github.com/
|
|
208
|
+
* update IComponent signatures ([e1a79bc](https://github.com/iotaledger/twin-background-task/commit/e1a79bc4dd813435c56e376f231a4b4ecd2276bf))
|
|
51
209
|
|
|
52
210
|
|
|
53
211
|
### Dependencies
|
|
@@ -56,12 +214,12 @@
|
|
|
56
214
|
* dependencies
|
|
57
215
|
* @twin.org/background-task-models bumped from 0.0.2-next.7 to 0.0.2-next.8
|
|
58
216
|
|
|
59
|
-
## [0.0.2-next.7](https://github.com/
|
|
217
|
+
## [0.0.2-next.7](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.2-next.6...background-task-scheduler-v0.0.2-next.7) (2025-08-29)
|
|
60
218
|
|
|
61
219
|
|
|
62
220
|
### Features
|
|
63
221
|
|
|
64
|
-
* eslint migration to flat config ([6c9136c](https://github.com/
|
|
222
|
+
* eslint migration to flat config ([6c9136c](https://github.com/iotaledger/twin-background-task/commit/6c9136c37bccdbbd109892d1503660aab7080d49))
|
|
65
223
|
|
|
66
224
|
|
|
67
225
|
### Dependencies
|
|
@@ -70,12 +228,12 @@
|
|
|
70
228
|
* dependencies
|
|
71
229
|
* @twin.org/background-task-models bumped from 0.0.2-next.6 to 0.0.2-next.7
|
|
72
230
|
|
|
73
|
-
## [0.0.2-next.6](https://github.com/
|
|
231
|
+
## [0.0.2-next.6](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.2-next.5...background-task-scheduler-v0.0.2-next.6) (2025-08-22)
|
|
74
232
|
|
|
75
233
|
|
|
76
234
|
### Features
|
|
77
235
|
|
|
78
|
-
* remove unused parameters ([1028b3c](https://github.com/
|
|
236
|
+
* remove unused parameters ([1028b3c](https://github.com/iotaledger/twin-background-task/commit/1028b3cc147c25da22a8ba8d7207acfb34f89cdb))
|
|
79
237
|
|
|
80
238
|
|
|
81
239
|
### Dependencies
|
|
@@ -84,12 +242,12 @@
|
|
|
84
242
|
* dependencies
|
|
85
243
|
* @twin.org/background-task-models bumped from 0.0.2-next.5 to 0.0.2-next.6
|
|
86
244
|
|
|
87
|
-
## [0.0.2-next.5](https://github.com/
|
|
245
|
+
## [0.0.2-next.5](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.2-next.4...background-task-scheduler-v0.0.2-next.5) (2025-08-20)
|
|
88
246
|
|
|
89
247
|
|
|
90
248
|
### Features
|
|
91
249
|
|
|
92
|
-
* update framework core ([a068098](https://github.com/
|
|
250
|
+
* update framework core ([a068098](https://github.com/iotaledger/twin-background-task/commit/a0680983d7923a1bfb980a67879019bb870ccc5d))
|
|
93
251
|
|
|
94
252
|
|
|
95
253
|
### Dependencies
|
|
@@ -98,12 +256,12 @@
|
|
|
98
256
|
* dependencies
|
|
99
257
|
* @twin.org/background-task-models bumped from 0.0.2-next.4 to 0.0.2-next.5
|
|
100
258
|
|
|
101
|
-
## [0.0.2-next.4](https://github.com/
|
|
259
|
+
## [0.0.2-next.4](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.2-next.3...background-task-scheduler-v0.0.2-next.4) (2025-07-23)
|
|
102
260
|
|
|
103
261
|
|
|
104
262
|
### Features
|
|
105
263
|
|
|
106
|
-
* background tasks immediately trigger ([a0a847b](https://github.com/
|
|
264
|
+
* background tasks immediately trigger ([a0a847b](https://github.com/iotaledger/twin-background-task/commit/a0a847ba9686adcd0460e810540959f87dcaeab1))
|
|
107
265
|
|
|
108
266
|
|
|
109
267
|
### Dependencies
|
|
@@ -112,12 +270,12 @@
|
|
|
112
270
|
* dependencies
|
|
113
271
|
* @twin.org/background-task-models bumped from 0.0.2-next.3 to 0.0.2-next.4
|
|
114
272
|
|
|
115
|
-
## [0.0.2-next.3](https://github.com/
|
|
273
|
+
## [0.0.2-next.3](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.2-next.2...background-task-scheduler-v0.0.2-next.3) (2025-07-21)
|
|
116
274
|
|
|
117
275
|
|
|
118
276
|
### Features
|
|
119
277
|
|
|
120
|
-
* rename task scheduler component to service ([f097a98](https://github.com/
|
|
278
|
+
* rename task scheduler component to service ([f097a98](https://github.com/iotaledger/twin-background-task/commit/f097a988c9ee0795aa55d74deda616365ec4ffb1))
|
|
121
279
|
|
|
122
280
|
|
|
123
281
|
### Dependencies
|
|
@@ -126,18 +284,18 @@
|
|
|
126
284
|
* dependencies
|
|
127
285
|
* @twin.org/background-task-models bumped from 0.0.2-next.2 to 0.0.2-next.3
|
|
128
286
|
|
|
129
|
-
## [0.0.2-next.2](https://github.com/
|
|
287
|
+
## [0.0.2-next.2](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.2-next.1...background-task-scheduler-v0.0.2-next.2) (2025-07-09)
|
|
130
288
|
|
|
131
289
|
|
|
132
290
|
### Features
|
|
133
291
|
|
|
134
|
-
* add task scheduler ([754d973](https://github.com/
|
|
135
|
-
* rename task scheduler component ([2f8aa59](https://github.com/
|
|
292
|
+
* add task scheduler ([754d973](https://github.com/iotaledger/twin-background-task/commit/754d973e7c8483e5e54e887c157661867d5a0375))
|
|
293
|
+
* rename task scheduler component ([2f8aa59](https://github.com/iotaledger/twin-background-task/commit/2f8aa59c069055ff020a3c0c149601f20c656022))
|
|
136
294
|
|
|
137
295
|
|
|
138
296
|
### Bug Fixes
|
|
139
297
|
|
|
140
|
-
* models import ([c830b0d](https://github.com/
|
|
298
|
+
* models import ([c830b0d](https://github.com/iotaledger/twin-background-task/commit/c830b0da4deb06f8aeca6fec8988be4da877e73b))
|
|
141
299
|
|
|
142
300
|
|
|
143
301
|
### Dependencies
|
|
@@ -146,18 +304,18 @@
|
|
|
146
304
|
* dependencies
|
|
147
305
|
* @twin.org/background-task-models bumped from 0.0.2-next.1 to 0.0.2-next.2
|
|
148
306
|
|
|
149
|
-
## [0.0.2-next.1](https://github.com/
|
|
307
|
+
## [0.0.2-next.1](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.2-next.0...background-task-scheduler-v0.0.2-next.1) (2025-07-09)
|
|
150
308
|
|
|
151
309
|
|
|
152
310
|
### Features
|
|
153
311
|
|
|
154
|
-
* add task scheduler ([754d973](https://github.com/
|
|
155
|
-
* rename task scheduler component ([2f8aa59](https://github.com/
|
|
312
|
+
* add task scheduler ([754d973](https://github.com/iotaledger/twin-background-task/commit/754d973e7c8483e5e54e887c157661867d5a0375))
|
|
313
|
+
* rename task scheduler component ([2f8aa59](https://github.com/iotaledger/twin-background-task/commit/2f8aa59c069055ff020a3c0c149601f20c656022))
|
|
156
314
|
|
|
157
315
|
|
|
158
316
|
### Bug Fixes
|
|
159
317
|
|
|
160
|
-
* models import ([c830b0d](https://github.com/
|
|
318
|
+
* models import ([c830b0d](https://github.com/iotaledger/twin-background-task/commit/c830b0da4deb06f8aeca6fec8988be4da877e73b))
|
|
161
319
|
|
|
162
320
|
|
|
163
321
|
### Dependencies
|
|
@@ -171,7 +329,7 @@
|
|
|
171
329
|
|
|
172
330
|
### Features
|
|
173
331
|
|
|
174
|
-
* release to production ([7ce9896](https://github.com/
|
|
332
|
+
* release to production ([7ce9896](https://github.com/iotaledger/twin-background-task/commit/7ce989659e6819f05655c86b1bda2a265af5d281))
|
|
175
333
|
|
|
176
334
|
|
|
177
335
|
### Dependencies
|
|
@@ -180,12 +338,12 @@
|
|
|
180
338
|
* dependencies
|
|
181
339
|
* @twin.org/background-task-models bumped from ^0.0.0 to ^0.0.1
|
|
182
340
|
|
|
183
|
-
## [0.0.1-next.21](https://github.com/
|
|
341
|
+
## [0.0.1-next.21](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.1-next.20...background-task-scheduler-v0.0.1-next.21) (2025-06-23)
|
|
184
342
|
|
|
185
343
|
|
|
186
344
|
### Features
|
|
187
345
|
|
|
188
|
-
* rename task scheduler component ([2f8aa59](https://github.com/
|
|
346
|
+
* rename task scheduler component ([2f8aa59](https://github.com/iotaledger/twin-background-task/commit/2f8aa59c069055ff020a3c0c149601f20c656022))
|
|
189
347
|
|
|
190
348
|
|
|
191
349
|
### Dependencies
|
|
@@ -194,17 +352,17 @@
|
|
|
194
352
|
* dependencies
|
|
195
353
|
* @twin.org/background-task-models bumped from 0.0.1-next.20 to 0.0.1-next.21
|
|
196
354
|
|
|
197
|
-
## [0.0.1-next.20](https://github.com/
|
|
355
|
+
## [0.0.1-next.20](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.1-next.19...background-task-scheduler-v0.0.1-next.20) (2025-06-23)
|
|
198
356
|
|
|
199
357
|
|
|
200
358
|
### Features
|
|
201
359
|
|
|
202
|
-
* add task scheduler ([754d973](https://github.com/
|
|
360
|
+
* add task scheduler ([754d973](https://github.com/iotaledger/twin-background-task/commit/754d973e7c8483e5e54e887c157661867d5a0375))
|
|
203
361
|
|
|
204
362
|
|
|
205
363
|
### Bug Fixes
|
|
206
364
|
|
|
207
|
-
* models import ([c830b0d](https://github.com/
|
|
365
|
+
* models import ([c830b0d](https://github.com/iotaledger/twin-background-task/commit/c830b0da4deb06f8aeca6fec8988be4da877e73b))
|
|
208
366
|
|
|
209
367
|
|
|
210
368
|
### Dependencies
|
|
@@ -213,12 +371,12 @@
|
|
|
213
371
|
* dependencies
|
|
214
372
|
* @twin.org/background-task-models bumped from 0.0.1-next.19 to 0.0.1-next.20
|
|
215
373
|
|
|
216
|
-
## [0.0.1-next.19](https://github.com/
|
|
374
|
+
## [0.0.1-next.19](https://github.com/iotaledger/twin-background-task/compare/background-task-scheduler-v0.0.1-next.18...background-task-scheduler-v0.0.1-next.19) (2025-06-23)
|
|
217
375
|
|
|
218
376
|
|
|
219
377
|
### Features
|
|
220
378
|
|
|
221
|
-
* add task scheduler ([754d973](https://github.com/
|
|
379
|
+
* add task scheduler ([754d973](https://github.com/iotaledger/twin-background-task/commit/754d973e7c8483e5e54e887c157661867d5a0375))
|
|
222
380
|
|
|
223
381
|
|
|
224
382
|
### Dependencies
|
|
@@ -227,4 +385,4 @@
|
|
|
227
385
|
* dependencies
|
|
228
386
|
* @twin.org/background-task-models bumped from 0.0.1-next.18 to 0.0.1-next.19
|
|
229
387
|
|
|
230
|
-
##
|
|
388
|
+
## Changelog
|
package/docs/examples.md
CHANGED
|
@@ -1 +1,95 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Background Task Scheduler Examples
|
|
2
|
+
|
|
3
|
+
Use these snippets to configure recurring schedules and monitor trigger state for background work.
|
|
4
|
+
|
|
5
|
+
## TaskSchedulerService
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { TaskSchedulerService } from '@twin.org/background-task-scheduler';
|
|
9
|
+
|
|
10
|
+
const scheduler = new TaskSchedulerService({
|
|
11
|
+
config: {
|
|
12
|
+
intervalMs: 10000,
|
|
13
|
+
stalledTaskTimeoutMs: 120000
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
console.log(scheduler.className()); // TaskSchedulerService
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { TaskSchedulerService } from '@twin.org/background-task-scheduler';
|
|
22
|
+
|
|
23
|
+
const scheduler = new TaskSchedulerService();
|
|
24
|
+
const taskId = 'report-refresh';
|
|
25
|
+
|
|
26
|
+
await scheduler.addTask(
|
|
27
|
+
taskId,
|
|
28
|
+
[
|
|
29
|
+
{
|
|
30
|
+
nextTriggerTime: Date.now() + 5000,
|
|
31
|
+
intervalMinutes: 10
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
nextTriggerTime: Date.now() + 30000,
|
|
35
|
+
intervalHours: 1
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
async () => {
|
|
39
|
+
const runAt = new Date().toISOString();
|
|
40
|
+
console.log('report-refresh runAt', runAt); // report-refresh runAt 2026-03-09T10:45:05.000Z
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const info = await scheduler.tasksInfo();
|
|
45
|
+
console.log(info.tasks[taskId].length); // 2
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { TaskSchedulerService } from '@twin.org/background-task-scheduler';
|
|
50
|
+
|
|
51
|
+
const scheduler = new TaskSchedulerService();
|
|
52
|
+
const taskId = 'cache-prune';
|
|
53
|
+
|
|
54
|
+
await scheduler.addTask(
|
|
55
|
+
taskId,
|
|
56
|
+
[
|
|
57
|
+
{
|
|
58
|
+
nextTriggerTime: Date.now() + 1000,
|
|
59
|
+
intervalMinutes: 5
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
async () => {
|
|
63
|
+
const runAt = new Date().toISOString();
|
|
64
|
+
console.log('cache-prune runAt', runAt); // cache-prune runAt 2026-03-09T10:45:01.000Z
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
await scheduler.removeTask(taskId);
|
|
69
|
+
|
|
70
|
+
const infoAfterRemoval = await scheduler.tasksInfo();
|
|
71
|
+
console.log(taskId in infoAfterRemoval.tasks); // false
|
|
72
|
+
|
|
73
|
+
await scheduler.stop();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## ScheduledTask
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { ScheduledTask } from '@twin.org/background-task-scheduler';
|
|
80
|
+
|
|
81
|
+
const scheduledTask = new ScheduledTask();
|
|
82
|
+
scheduledTask.id = 'nightly-index';
|
|
83
|
+
scheduledTask.lastRunTime = Date.now();
|
|
84
|
+
|
|
85
|
+
console.log(scheduledTask.id); // nightly-index
|
|
86
|
+
console.log(typeof scheduledTask.lastRunTime); // number
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## initSchema
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { initSchema } from '@twin.org/background-task-scheduler';
|
|
93
|
+
|
|
94
|
+
initSchema();
|
|
95
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Class: ScheduledTask
|
|
2
|
+
|
|
3
|
+
Class defining a scheduled task.
|
|
4
|
+
|
|
5
|
+
## Constructors
|
|
6
|
+
|
|
7
|
+
### Constructor
|
|
8
|
+
|
|
9
|
+
> **new ScheduledTask**(): `ScheduledTask`
|
|
10
|
+
|
|
11
|
+
#### Returns
|
|
12
|
+
|
|
13
|
+
`ScheduledTask`
|
|
14
|
+
|
|
15
|
+
## Properties
|
|
16
|
+
|
|
17
|
+
### id {#id}
|
|
18
|
+
|
|
19
|
+
> **id**: `string`
|
|
20
|
+
|
|
21
|
+
The id.
|
|
22
|
+
|
|
23
|
+
***
|
|
24
|
+
|
|
25
|
+
### lastRunTime? {#lastruntime}
|
|
26
|
+
|
|
27
|
+
> `optional` **lastRunTime?**: `number`
|
|
28
|
+
|
|
29
|
+
The last run time of the task, if undefined waiting for next run.
|
|
@@ -28,7 +28,7 @@ The options for the scheduler.
|
|
|
28
28
|
|
|
29
29
|
## Properties
|
|
30
30
|
|
|
31
|
-
### CLASS\_NAME
|
|
31
|
+
### CLASS\_NAME {#class_name}
|
|
32
32
|
|
|
33
33
|
> `readonly` `static` **CLASS\_NAME**: `string`
|
|
34
34
|
|
|
@@ -36,7 +36,7 @@ Runtime name for the class.
|
|
|
36
36
|
|
|
37
37
|
## Methods
|
|
38
38
|
|
|
39
|
-
### className()
|
|
39
|
+
### className() {#classname}
|
|
40
40
|
|
|
41
41
|
> **className**(): `string`
|
|
42
42
|
|
|
@@ -54,7 +54,7 @@ The class name of the component.
|
|
|
54
54
|
|
|
55
55
|
***
|
|
56
56
|
|
|
57
|
-
### stop()
|
|
57
|
+
### stop() {#stop}
|
|
58
58
|
|
|
59
59
|
> **stop**(`nodeLoggingComponentType?`): `Promise`\<`void`\>
|
|
60
60
|
|
|
@@ -80,7 +80,7 @@ Nothing.
|
|
|
80
80
|
|
|
81
81
|
***
|
|
82
82
|
|
|
83
|
-
### addTask()
|
|
83
|
+
### addTask() {#addtask}
|
|
84
84
|
|
|
85
85
|
> **addTask**(`taskId`, `times`, `taskCallback`): `Promise`\<`void`\>
|
|
86
86
|
|
|
@@ -118,7 +118,7 @@ Nothing.
|
|
|
118
118
|
|
|
119
119
|
***
|
|
120
120
|
|
|
121
|
-
### removeTask()
|
|
121
|
+
### removeTask() {#removetask}
|
|
122
122
|
|
|
123
123
|
> **removeTask**(`taskId`): `Promise`\<`void`\>
|
|
124
124
|
|
|
@@ -144,7 +144,7 @@ Nothing.
|
|
|
144
144
|
|
|
145
145
|
***
|
|
146
146
|
|
|
147
|
-
### tasksInfo()
|
|
147
|
+
### tasksInfo() {#tasksinfo}
|
|
148
148
|
|
|
149
149
|
> **tasksInfo**(): `Promise`\<`IScheduledTaskInfo`\>
|
|
150
150
|
|
package/docs/reference/index.md
CHANGED
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## Classes
|
|
4
4
|
|
|
5
|
+
- [ScheduledTask](classes/ScheduledTask.md)
|
|
5
6
|
- [TaskSchedulerService](classes/TaskSchedulerService.md)
|
|
6
7
|
|
|
7
8
|
## Interfaces
|
|
8
9
|
|
|
9
10
|
- [ITaskSchedulerConfig](interfaces/ITaskSchedulerConfig.md)
|
|
10
11
|
- [ITaskSchedulerConstructorOptions](interfaces/ITaskSchedulerConstructorOptions.md)
|
|
12
|
+
|
|
13
|
+
## Functions
|
|
14
|
+
|
|
15
|
+
- [initSchema](functions/initSchema.md)
|
|
@@ -4,9 +4,9 @@ Interface for the task scheduler configuration.
|
|
|
4
4
|
|
|
5
5
|
## Properties
|
|
6
6
|
|
|
7
|
-
###
|
|
7
|
+
### intervalMs? {#intervalms}
|
|
8
8
|
|
|
9
|
-
> `optional` **
|
|
9
|
+
> `optional` **intervalMs?**: `number`
|
|
10
10
|
|
|
11
11
|
The interval between checks for running tasks, defaults to 1 minute since that is the resolution of the tasks.
|
|
12
12
|
|
|
@@ -15,3 +15,17 @@ The interval between checks for running tasks, defaults to 1 minute since that i
|
|
|
15
15
|
```ts
|
|
16
16
|
60000
|
|
17
17
|
```
|
|
18
|
+
|
|
19
|
+
***
|
|
20
|
+
|
|
21
|
+
### stalledTaskTimeoutMs? {#stalledtasktimeoutms}
|
|
22
|
+
|
|
23
|
+
> `optional` **stalledTaskTimeoutMs?**: `number`
|
|
24
|
+
|
|
25
|
+
The time in milliseconds after which a task that is still marked as running is considered stalled and can be run again.
|
|
26
|
+
|
|
27
|
+
#### Default
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
300000
|
|
31
|
+
```
|
|
@@ -4,9 +4,9 @@ Options for the task scheduler constructor.
|
|
|
4
4
|
|
|
5
5
|
## Properties
|
|
6
6
|
|
|
7
|
-
### loggingComponentType?
|
|
7
|
+
### loggingComponentType? {#loggingcomponenttype}
|
|
8
8
|
|
|
9
|
-
> `optional` **loggingComponentType
|
|
9
|
+
> `optional` **loggingComponentType?**: `string`
|
|
10
10
|
|
|
11
11
|
The logging component type.
|
|
12
12
|
|
|
@@ -18,8 +18,22 @@ logging
|
|
|
18
18
|
|
|
19
19
|
***
|
|
20
20
|
|
|
21
|
-
###
|
|
21
|
+
### scheduledTaskEntityStorageType? {#scheduledtaskentitystoragetype}
|
|
22
22
|
|
|
23
|
-
> `optional` **
|
|
23
|
+
> `optional` **scheduledTaskEntityStorageType?**: `string`
|
|
24
|
+
|
|
25
|
+
The scheduled task entity storage connector type.
|
|
26
|
+
|
|
27
|
+
#### Default
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
scheduled-task
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
***
|
|
34
|
+
|
|
35
|
+
### config? {#config}
|
|
36
|
+
|
|
37
|
+
> `optional` **config?**: [`ITaskSchedulerConfig`](ITaskSchedulerConfig.md)
|
|
24
38
|
|
|
25
39
|
The configuration for the task scheduler.
|
package/locales/en.json
CHANGED
|
@@ -10,5 +10,10 @@
|
|
|
10
10
|
"taskRemoved": "Task with id \"{id}\" removed",
|
|
11
11
|
"taskTriggered": "Task with id \"{id}\" triggered at time \"{time}\""
|
|
12
12
|
}
|
|
13
|
+
},
|
|
14
|
+
"warn": {
|
|
15
|
+
"taskSchedulerService": {
|
|
16
|
+
"taskStalled": "Task with id \"{id}\" is stalled, last run at \"{lastRunTime}\" and exceeded timeout \"{stalledTaskTimeoutMs}\" ms"
|
|
17
|
+
}
|
|
13
18
|
}
|
|
14
19
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/background-task-scheduler",
|
|
3
|
-
"version": "0.0.3-next.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.3-next.11",
|
|
4
|
+
"description": "Schedules background tasks for one-off or recurring execution windows",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/
|
|
7
|
+
"url": "git+https://github.com/iotaledger/twin-background-task.git",
|
|
8
8
|
"directory": "packages/background-task-scheduler"
|
|
9
9
|
},
|
|
10
10
|
"author": "martyn.janes@iota.org",
|
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
"node": ">=20.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@twin.org/background-task-models": "0.0.3-next.
|
|
17
|
+
"@twin.org/background-task-models": "0.0.3-next.11",
|
|
18
18
|
"@twin.org/core": "next",
|
|
19
|
+
"@twin.org/entity-storage-models": "next",
|
|
19
20
|
"@twin.org/logging-models": "next",
|
|
20
21
|
"@twin.org/nameof": "next"
|
|
21
22
|
},
|
|
@@ -48,7 +49,7 @@
|
|
|
48
49
|
"async"
|
|
49
50
|
],
|
|
50
51
|
"bugs": {
|
|
51
|
-
"url": "git+https://github.com/
|
|
52
|
+
"url": "git+https://github.com/iotaledger/twin-background-task/issues"
|
|
52
53
|
},
|
|
53
54
|
"homepage": "https://twindev.org"
|
|
54
55
|
}
|