mongodash 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dashboard/favicon.ico +0 -0
- package/dist/dashboard/index.html +4 -3
- package/dist/lib/src/OnError.js +20 -11
- package/dist/lib/src/OnError.js.map +1 -1
- package/dist/lib/src/OnInfo.js +20 -11
- package/dist/lib/src/OnInfo.js.map +1 -1
- package/dist/lib/src/createContinuousLock.js +3 -2
- package/dist/lib/src/createContinuousLock.js.map +1 -1
- package/dist/lib/src/createSecureHandler.js +20 -0
- package/dist/lib/src/createSecureHandler.js.map +1 -0
- package/dist/lib/src/cronTasks.js +48 -34
- package/dist/lib/src/cronTasks.js.map +1 -1
- package/dist/lib/src/getCollection.js +4 -0
- package/dist/lib/src/getCollection.js.map +1 -1
- package/dist/lib/src/index.js +41 -39
- package/dist/lib/src/index.js.map +1 -1
- package/dist/lib/src/reactiveTasks/ReactiveTaskManager.js +1 -1
- package/dist/lib/src/reactiveTasks/ReactiveTaskManager.js.map +1 -1
- package/dist/lib/src/reactiveTasks/ReactiveTaskOps.js +13 -5
- package/dist/lib/src/reactiveTasks/ReactiveTaskOps.js.map +1 -1
- package/dist/lib/src/reactiveTasks/ReactiveTaskRepository.js +61 -67
- package/dist/lib/src/reactiveTasks/ReactiveTaskRepository.js.map +1 -1
- package/dist/lib/src/reactiveTasks/ReactiveTaskTypes.js +2 -1
- package/dist/lib/src/reactiveTasks/ReactiveTaskTypes.js.map +1 -1
- package/dist/lib/src/reactiveTasks/ReactiveTaskWorker.js +1 -3
- package/dist/lib/src/reactiveTasks/ReactiveTaskWorker.js.map +1 -1
- package/dist/lib/src/reactiveTasks/index.js +14 -15
- package/dist/lib/src/reactiveTasks/index.js.map +1 -1
- package/dist/lib/src/task-management/OperationalTaskController.js +21 -3
- package/dist/lib/src/task-management/OperationalTaskController.js.map +1 -1
- package/dist/lib/src/withLock.js +13 -8
- package/dist/lib/src/withLock.js.map +1 -1
- package/dist/lib/src/withTransaction.js +4 -10
- package/dist/lib/src/withTransaction.js.map +1 -1
- package/dist/types/src/OnError.d.ts +10 -1
- package/dist/types/src/OnInfo.d.ts +10 -1
- package/dist/types/src/createContinuousLock.d.ts +3 -4
- package/dist/types/src/createSecureHandler.d.ts +5 -0
- package/dist/types/src/cronTasks.d.ts +7 -11
- package/dist/types/src/getCollection.d.ts +1 -0
- package/dist/types/src/index.d.ts +7 -7
- package/dist/types/src/reactiveTasks/ReactiveTaskTypes.d.ts +21 -5
- package/dist/types/src/reactiveTasks/index.d.ts +0 -4
- package/dist/types/src/task-management/OperationalTaskController.d.ts +1 -1
- package/dist/types/src/withLock.d.ts +2 -5
- package/dist/types/src/withTransaction.d.ts +2 -9
- package/docs/.vitepress/cache/deps/_metadata.json +6 -6
- package/docs/.vitepress/config.mts +1 -1
- package/docs/reactive-tasks/configuration.md +1 -1
- package/docs/reactive-tasks/core-concepts.md +19 -0
- package/docs/reactive-tasks/evolution.md +1 -1
- package/docs/reactive-tasks/guides.md +47 -7
- package/docs/reactive-tasks/management.md +1 -1
- package/docs/reactive-tasks/monitoring.md +1 -1
- package/docs/reactive-tasks/reconciliation.md +1 -1
- package/package.json +1 -1
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OperationalTaskController = void 0;
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
const mongodb_1 = require("mongodb");
|
|
4
7
|
const cronTasks_1 = require("../cronTasks");
|
|
5
8
|
const getMongoClient_1 = require("../getMongoClient");
|
|
6
|
-
const
|
|
9
|
+
const OnInfo_1 = require("../OnInfo");
|
|
10
|
+
const ReactiveTaskTypes_1 = require("../reactiveTasks/ReactiveTaskTypes");
|
|
7
11
|
class OperationalTaskController {
|
|
8
12
|
constructor(scheduler) {
|
|
9
13
|
this.scheduler = scheduler;
|
|
@@ -45,7 +49,7 @@ class OperationalTaskController {
|
|
|
45
49
|
this.scheduler.getTaskManager().getTasks(query, {
|
|
46
50
|
limit: Number(params.limit || 50),
|
|
47
51
|
skip: Number(params.skip || 0),
|
|
48
|
-
sort: { field: '
|
|
52
|
+
sort: { field: 'nextRunAt', direction: 1 },
|
|
49
53
|
}),
|
|
50
54
|
this.scheduler.getTaskManager().getTaskStats(statsQuery),
|
|
51
55
|
]);
|
|
@@ -72,7 +76,15 @@ class OperationalTaskController {
|
|
|
72
76
|
if (body.sourceDocId) {
|
|
73
77
|
query.sourceDocFilter = this.createSmartIdFilter(body.sourceDocId);
|
|
74
78
|
}
|
|
75
|
-
|
|
79
|
+
const result = await this.scheduler.getTaskManager().retryTasks(query);
|
|
80
|
+
(0, OnInfo_1.onInfo)({
|
|
81
|
+
message: `Manual intervention via Dashboard: Retry tasks matching ${JSON.stringify(body)}`,
|
|
82
|
+
code: ReactiveTaskTypes_1.CODE_MANUAL_TRIGGER,
|
|
83
|
+
action: 'retry',
|
|
84
|
+
params: body,
|
|
85
|
+
modifiedCount: result.modifiedCount,
|
|
86
|
+
});
|
|
87
|
+
return result;
|
|
76
88
|
}
|
|
77
89
|
createSmartIdFilter(sourceDocId) {
|
|
78
90
|
const input = sourceDocId.trim();
|
|
@@ -102,6 +114,12 @@ class OperationalTaskController {
|
|
|
102
114
|
if (!body.taskId)
|
|
103
115
|
throw new Error('taskId is required');
|
|
104
116
|
await (0, cronTasks_1.triggerCronTask)(body.taskId);
|
|
117
|
+
(0, OnInfo_1.onInfo)({
|
|
118
|
+
message: `Manual intervention via Dashboard: Triggered Cron Task '${body.taskId}'`,
|
|
119
|
+
code: ReactiveTaskTypes_1.CODE_MANUAL_TRIGGER,
|
|
120
|
+
action: 'triggerCron',
|
|
121
|
+
taskId: body.taskId,
|
|
122
|
+
});
|
|
105
123
|
return { success: true };
|
|
106
124
|
}
|
|
107
125
|
async getInfo() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OperationalTaskController.js","sourceRoot":"","sources":["../../../../src/task-management/OperationalTaskController.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"OperationalTaskController.js","sourceRoot":"","sources":["../../../../src/task-management/OperationalTaskController.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/src/withLock.js
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.LockAlreadyAcquiredError = void 0;
|
|
4
|
-
exports.
|
|
4
|
+
exports.reset = reset;
|
|
5
5
|
exports.isLockAlreadyAcquiredError = isLockAlreadyAcquiredError;
|
|
6
6
|
exports.withLock = withLock;
|
|
7
7
|
// import * as _debug from 'debug';
|
|
8
8
|
const mongodb_1 = require("mongodb");
|
|
9
9
|
const createContinuousLock_1 = require("./createContinuousLock");
|
|
10
10
|
const getCollection_1 = require("./getCollection");
|
|
11
|
-
// const debug = _debug('mongodash:withLock');
|
|
12
|
-
let onError;
|
|
13
|
-
function init(options) {
|
|
14
|
-
onError = options.onError;
|
|
15
|
-
}
|
|
16
11
|
const lockAcquiredMessage = 'The lock is already acquired.';
|
|
17
12
|
const expirationKey = 'expiresAt';
|
|
18
13
|
let collectionPromise;
|
|
@@ -26,6 +21,11 @@ async function getLockerCollection() {
|
|
|
26
21
|
}
|
|
27
22
|
return collectionPromise;
|
|
28
23
|
}
|
|
24
|
+
function reset() {
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
collectionPromise = null;
|
|
28
|
+
}
|
|
29
29
|
class LockAlreadyAcquiredError extends Error {
|
|
30
30
|
constructor(key) {
|
|
31
31
|
super(lockAcquiredMessage);
|
|
@@ -40,7 +40,12 @@ function isLockAlreadyAcquiredError(err, key) {
|
|
|
40
40
|
}
|
|
41
41
|
return key ? err.key === key : true;
|
|
42
42
|
}
|
|
43
|
-
async function withLock(key, callback,
|
|
43
|
+
async function withLock(key, callback, options) {
|
|
44
|
+
var _a, _b, _c;
|
|
45
|
+
const _options = options !== null && options !== void 0 ? options : {};
|
|
46
|
+
const maxWaitForLock = (_a = _options.maxWaitForLock) !== null && _a !== void 0 ? _a : 3 * 1000;
|
|
47
|
+
const startingDelay = (_b = _options.startingDelay) !== null && _b !== void 0 ? _b : 50;
|
|
48
|
+
const expireIn = (_c = _options.expireIn) !== null && _c !== void 0 ? _c : 15 * 1000;
|
|
44
49
|
const lockId = new mongodb_1.ObjectId();
|
|
45
50
|
const stringKey = `${key}`;
|
|
46
51
|
const maxDate = new Date(Date.now() + maxWaitForLock);
|
|
@@ -94,7 +99,7 @@ async function withLock(key, callback, { maxWaitForLock = 3 * 1000, startingDela
|
|
|
94
99
|
}
|
|
95
100
|
}
|
|
96
101
|
}
|
|
97
|
-
const stopContinuousLock = (0, createContinuousLock_1.createContinuousLock)(collection, stringKey, expirationKey, expireIn
|
|
102
|
+
const stopContinuousLock = (0, createContinuousLock_1.createContinuousLock)(collection, stringKey, expirationKey, expireIn);
|
|
98
103
|
const cleanUp = () => Promise.all([stopContinuousLock(), releaseLock()]);
|
|
99
104
|
let value;
|
|
100
105
|
let err;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withLock.js","sourceRoot":"","sources":["../../../src/withLock.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;
|
|
1
|
+
{"version":3,"file":"withLock.js","sourceRoot":"","sources":["../../../src/withLock.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.init = init;
|
|
4
3
|
exports.registerPostCommitHook = registerPostCommitHook;
|
|
5
4
|
exports.withTransaction = withTransaction;
|
|
6
5
|
const getMongoClient_1 = require("./getMongoClient");
|
|
6
|
+
const OnError_1 = require("./OnError");
|
|
7
7
|
const postCommitHooks = new WeakMap();
|
|
8
|
-
let _onError;
|
|
9
|
-
let _onInfo;
|
|
10
|
-
function init(options) {
|
|
11
|
-
_onError = options.onError;
|
|
12
|
-
_onInfo = options.onInfo;
|
|
13
|
-
}
|
|
14
8
|
function registerPostCommitHook(session, hook) {
|
|
15
9
|
if (!session.inTransaction()) {
|
|
16
10
|
throw new Error('It is not possible to register a post commit hook without active transaction.');
|
|
@@ -21,20 +15,20 @@ function registerPostCommitHook(session, hook) {
|
|
|
21
15
|
}
|
|
22
16
|
hooks.push(hook);
|
|
23
17
|
}
|
|
24
|
-
async function withTransaction(callback
|
|
18
|
+
async function withTransaction(callback) {
|
|
25
19
|
const clientSession = (0, getMongoClient_1.getMongoClient)().startSession();
|
|
26
20
|
postCommitHooks.set(clientSession, []);
|
|
27
21
|
try {
|
|
28
22
|
let returnValue;
|
|
29
23
|
await clientSession.withTransaction(async () => {
|
|
30
24
|
returnValue = await callback(clientSession);
|
|
31
|
-
}
|
|
25
|
+
});
|
|
32
26
|
const hooks = postCommitHooks.get(clientSession);
|
|
33
27
|
if (hooks.length > 0) {
|
|
34
28
|
const results = await Promise.allSettled(hooks.map((hook) => hook()));
|
|
35
29
|
results.forEach((result) => {
|
|
36
30
|
if (result.status === 'rejected') {
|
|
37
|
-
|
|
31
|
+
(0, OnError_1.onError)(result.reason);
|
|
38
32
|
}
|
|
39
33
|
});
|
|
40
34
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withTransaction.js","sourceRoot":"","sources":["../../../src/withTransaction.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;
|
|
1
|
+
{"version":3,"file":"withTransaction.js","sourceRoot":"","sources":["../../../src/withTransaction.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAYb,wDAYC;AAED,0CA4BC;AAjDD,qDAAkD;AAClD,uCAAoC;AAIpC,MAAM,eAAe,GAAG,IAAI,OAAO,EAAmC,CAAC;AAEvE,SAAgB,sBAAsB,CAAC,OAAsB,EAAE,IAAoB;IAC/E,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAC;IACrG,CAAC;IAED,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAE3C,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,wGAAwG,CAAC,CAAC;IAC9H,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAEM,KAAK,UAAU,eAAe,CAAI,QAAgD;IACrF,MAAM,aAAa,GAAG,IAAA,+BAAc,GAAE,CAAC,YAAY,EAAE,CAAC;IAEtD,eAAe,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAEvC,IAAI,CAAC;QACD,IAAI,WAAc,CAAC;QAEnB,MAAM,aAAa,CAAC,eAAe,CAAC,KAAK,IAAI,EAAE;YAC3C,WAAW,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,aAAa,CAAE,CAAC;QAElD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACtE,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;gBACvB,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;oBAC/B,IAAA,iBAAO,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC3B,CAAC;YACL,CAAC,CAAC,CAAC;QACP,CAAC;QAED,OAAO,WAAY,CAAC;IACxB,CAAC;YAAS,CAAC;QACP,eAAe,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QACtC,MAAM,aAAa,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC;AACL,CAAC"}
|
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
export type OnError = (error: Error) => void;
|
|
2
2
|
export declare const defaultOnError: OnError;
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Updates the global onError handler.
|
|
5
|
+
* Automatically wraps the provided handler with secureOnError for safety.
|
|
6
|
+
*/
|
|
7
|
+
export declare function setGlobalOnError(onError: OnError): void;
|
|
8
|
+
/**
|
|
9
|
+
* Global wrapper that delegates to the currently configured onError handler.
|
|
10
|
+
* Can be imported and used directly by any component.
|
|
11
|
+
*/
|
|
12
|
+
export declare const onError: OnError;
|
|
@@ -3,4 +3,13 @@ export type OnInfo = (info: {
|
|
|
3
3
|
code: string;
|
|
4
4
|
} & Record<string, unknown>) => void;
|
|
5
5
|
export declare const defaultOnInfo: OnInfo;
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Updates the global onInfo handler.
|
|
8
|
+
* Automatically wraps the provided handler with secureOnInfo for safety.
|
|
9
|
+
*/
|
|
10
|
+
export declare function setGlobalOnInfo(onInfo: OnInfo): void;
|
|
11
|
+
/**
|
|
12
|
+
* Global wrapper that delegates to the currently configured onInfo handler.
|
|
13
|
+
* Can be imported and used directly by any component.
|
|
14
|
+
*/
|
|
15
|
+
export declare const onInfo: OnInfo;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { Collection } from 'mongodb';
|
|
2
|
-
import { OnError } from './OnError';
|
|
1
|
+
import { Collection, ObjectId } from 'mongodb';
|
|
3
2
|
type StopContinuousLock = () => Promise<void>;
|
|
4
3
|
export declare function createContinuousLock<DocumentType extends {
|
|
5
|
-
_id: string;
|
|
6
|
-
}>(collection: Collection<DocumentType>, documentId:
|
|
4
|
+
_id: string | ObjectId;
|
|
5
|
+
}>(collection: Collection<DocumentType>, documentId: DocumentType['_id'], lockProperty: keyof DocumentType, lockTime: number): StopContinuousLock;
|
|
7
6
|
export {};
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { CronExpressionOptions } from 'cron-parser';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
export interface InitOptions {
|
|
3
|
+
runCronTasks: boolean;
|
|
4
|
+
cronExpressionParserOptions: CronExpressionOptions;
|
|
5
|
+
cronTaskCaller: CronTaskCaller;
|
|
6
|
+
cronTaskFilter: CronTaskFilter;
|
|
7
|
+
}
|
|
8
|
+
export declare function init(options: InitOptions): void;
|
|
4
9
|
export declare const CODE_CRON_TASK_STARTED = "cronTaskStarted";
|
|
5
10
|
export declare const CODE_CRON_TASK_FINISHED = "cronTaskFinished";
|
|
6
11
|
export declare const CODE_CRON_TASK_SCHEDULED = "cronTaskScheduled";
|
|
@@ -50,15 +55,6 @@ export interface CronTaskFilter {
|
|
|
50
55
|
}): boolean;
|
|
51
56
|
}
|
|
52
57
|
export declare function runCronTask(taskId: TaskId): Promise<void>;
|
|
53
|
-
export type InitOptions = {
|
|
54
|
-
runCronTasks: boolean;
|
|
55
|
-
cronExpressionParserOptions: CronExpressionOptions;
|
|
56
|
-
onError: OnError;
|
|
57
|
-
onInfo: OnInfo;
|
|
58
|
-
cronTaskCaller: CronTaskCaller;
|
|
59
|
-
cronTaskFilter: CronTaskFilter;
|
|
60
|
-
};
|
|
61
|
-
export declare function init(initOptions: InitOptions): void;
|
|
62
58
|
export declare function stopCronTasks(): void;
|
|
63
59
|
export declare function startCronTasks(): void;
|
|
64
60
|
export declare function scheduleCronTaskImmediately(taskId: TaskId): Promise<void>;
|
|
@@ -11,4 +11,5 @@ export type InitOptions = {
|
|
|
11
11
|
collectionFactory: CollectionFactory | null;
|
|
12
12
|
};
|
|
13
13
|
export declare function init(options: InitOptions): void;
|
|
14
|
+
export declare function reset(): void;
|
|
14
15
|
export declare function getCollection<T extends Document>(name: string): Collection<T>;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
+
import { Collection } from 'mongodb';
|
|
1
2
|
import { InitOptions as CronTasksInitOptions } from './cronTasks';
|
|
2
|
-
import { InitOptions as ReactiveTasksInitOptions } from './reactiveTasks';
|
|
3
3
|
import { InitOptions as GetCollectionInitOptions } from './getCollection';
|
|
4
4
|
import { InitOptions as GetMongoClientInitOptions } from './getMongoClient';
|
|
5
5
|
import { OnError } from './OnError';
|
|
6
6
|
import { OnInfo } from './OnInfo';
|
|
7
|
-
import {
|
|
8
|
-
export {
|
|
7
|
+
import { InitOptions as ReactiveTasksInitOptions } from './reactiveTasks';
|
|
8
|
+
export { CODE_CRON_TASK_FAILED, CODE_CRON_TASK_FINISHED, CODE_CRON_TASK_SCHEDULED, CODE_CRON_TASK_STARTED, CronPagedResult, cronTask, CronTaskQuery, CronTaskRecord, CronTaskStatus, getCronTasksList, Interval, runCronTask, scheduleCronTaskImmediately, startCronTasks, stopCronTasks, TaskFunction, TaskId, triggerCronTask, } from './cronTasks';
|
|
9
9
|
export { getCollection } from './getCollection';
|
|
10
10
|
export { getMongoClient } from './getMongoClient';
|
|
11
11
|
export { OnError } from './OnError';
|
|
12
|
-
export { withLock, isLockAlreadyAcquiredError, WithLockOptions, LockAlreadyAcquiredError } from './withLock';
|
|
13
|
-
export { withTransaction, registerPostCommitHook, PostCommitHook } from './withTransaction';
|
|
14
|
-
export { reactiveTask, ReactiveTask, ReactiveTaskHandler, TaskConditionFailedError, startReactiveTasks, stopReactiveTasks, getPrometheusMetrics, _scheduler, CODE_REACTIVE_TASK_STARTED, CODE_REACTIVE_TASK_FINISHED, CODE_REACTIVE_TASK_FAILED, CODE_REACTIVE_TASK_PLANNER_STARTED, CODE_REACTIVE_TASK_PLANNER_STOPPED, CODE_REACTIVE_TASK_PLANNER_RECONCILIATION_STARTED, CODE_REACTIVE_TASK_PLANNER_RECONCILIATION_FINISHED, CODE_REACTIVE_TASK_PLANNER_STREAM_ERROR, CODE_REACTIVE_TASK_LEADER_LOCK_LOST, getReactiveTasks, countReactiveTasks, retryReactiveTasks, } from './reactiveTasks';
|
|
15
12
|
export { processInBatches, ProcessInBatchesOptions, ProcessInBatchesResult } from './processInBatches';
|
|
16
|
-
export {
|
|
13
|
+
export { CODE_REACTIVE_TASK_FAILED, CODE_REACTIVE_TASK_FINISHED, CODE_REACTIVE_TASK_LEADER_LOCK_LOST, CODE_REACTIVE_TASK_PLANNER_RECONCILIATION_FINISHED, CODE_REACTIVE_TASK_PLANNER_RECONCILIATION_STARTED, CODE_REACTIVE_TASK_PLANNER_STARTED, CODE_REACTIVE_TASK_PLANNER_STOPPED, CODE_REACTIVE_TASK_PLANNER_STREAM_ERROR, CODE_REACTIVE_TASK_STARTED, countReactiveTasks, getPrometheusMetrics, getReactiveTasks, reactiveTask, ReactiveTask, ReactiveTaskHandler, retryReactiveTasks, startReactiveTasks, stopReactiveTasks, TaskConditionFailedError, _scheduler, } from './reactiveTasks';
|
|
14
|
+
export { OperationalTaskController, serveDashboard } from './task-management';
|
|
15
|
+
export { isLockAlreadyAcquiredError, LockAlreadyAcquiredError, withLock, WithLockOptions } from './withLock';
|
|
16
|
+
export { PostCommitHook, registerPostCommitHook, withTransaction } from './withTransaction';
|
|
17
17
|
type PackageOptions = {
|
|
18
18
|
onError?: OnError;
|
|
19
19
|
onInfo?: OnInfo;
|
|
@@ -33,16 +33,25 @@ export interface ReactiveTaskRecord<T = Document> {
|
|
|
33
33
|
sourceDocId: WithId<T>['_id'];
|
|
34
34
|
status: ReactiveTaskStatus;
|
|
35
35
|
attempts: number;
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* The effective time used for polling.
|
|
38
|
+
* - Pending: Time when the task becomes eligible to run.
|
|
39
|
+
* - Processing: Time when the lock expires (zombie recovery).
|
|
40
|
+
* - Completed/Failed: NULL (not indexed, not polled).
|
|
41
|
+
*/
|
|
42
|
+
nextRunAt: Date | null;
|
|
43
|
+
/**
|
|
44
|
+
* The original time the task was first scheduled to run.
|
|
45
|
+
* This preserves the original baseline for global lag calculation.
|
|
46
|
+
*/
|
|
47
|
+
dueAt: Date;
|
|
37
48
|
createdAt: Date;
|
|
38
49
|
updatedAt: Date;
|
|
39
50
|
startedAt?: Date | null;
|
|
40
51
|
completedAt?: Date | null;
|
|
41
|
-
lockExpiresAt?: Date | null;
|
|
42
52
|
firstErrorAt?: Date | null;
|
|
43
53
|
lastError?: string | null;
|
|
44
54
|
lastFinalizedAt?: Date | null;
|
|
45
|
-
initialScheduledAt?: Date | null;
|
|
46
55
|
lastObservedValues?: Record<string, unknown> | null;
|
|
47
56
|
lastSuccess?: {
|
|
48
57
|
at: Date;
|
|
@@ -131,7 +140,7 @@ export interface ReactiveTaskContext<T = Document> {
|
|
|
131
140
|
* Defers the task execution to a later time.
|
|
132
141
|
* The task will remain 'pending' (or effectively so) until the specified time.
|
|
133
142
|
* Use this for temporary external failures (e.g. rate limits) or to postpone processing.
|
|
134
|
-
* This preserves the original `
|
|
143
|
+
* This preserves the original baseline `dueAt` for global lag calculation.
|
|
135
144
|
*/
|
|
136
145
|
deferCurrent(delay: number | Date): void;
|
|
137
146
|
/**
|
|
@@ -224,7 +233,7 @@ export interface ReactiveTask<T extends Document> {
|
|
|
224
233
|
*/
|
|
225
234
|
filter?: Filter<T>;
|
|
226
235
|
handler: ReactiveTaskHandler<T>;
|
|
227
|
-
/** Time (ms) or interval description (e.g. "500ms", "1s") to postpone
|
|
236
|
+
/** Time (ms) or interval description (e.g. "500ms", "1s") to postpone execution on change (Debouncing). Default: 1000ms */
|
|
228
237
|
debounce?: number | string;
|
|
229
238
|
/** Retry Policy configuration */
|
|
230
239
|
retryPolicy?: RetryPolicy;
|
|
@@ -303,6 +312,12 @@ export interface ReactiveTaskSchedulerOptions {
|
|
|
303
312
|
* Default: '24h'
|
|
304
313
|
*/
|
|
305
314
|
reactiveTaskCleanupInterval?: number | string;
|
|
315
|
+
/**
|
|
316
|
+
* Timeout for the visibility lock on tasks (ms).
|
|
317
|
+
* Tasks that take longer than this will be picked up by other workers (if lock renewal fails).
|
|
318
|
+
* Default: 60000 (1m)
|
|
319
|
+
*/
|
|
320
|
+
visibilityTimeoutMs?: number;
|
|
306
321
|
}
|
|
307
322
|
/**
|
|
308
323
|
* Filter function to restrict which tasks are processed by the worker.
|
|
@@ -329,6 +344,7 @@ export declare const CODE_REACTIVE_TASK_PLANNER_STREAM_ERROR = "reactiveTaskPlan
|
|
|
329
344
|
export declare const CODE_REACTIVE_TASK_LEADER_LOCK_LOST = "reactiveTaskLeaderLockLost";
|
|
330
345
|
export declare const CODE_REACTIVE_TASK_INITIALIZED = "reactiveTaskInitialized";
|
|
331
346
|
export declare const CODE_REACTIVE_TASK_CLEANUP = "reactiveTaskCleanup";
|
|
347
|
+
export declare const CODE_MANUAL_TRIGGER = "manualTrigger";
|
|
332
348
|
export declare const REACTIVE_TASK_META_DOC_ID = "_mongodash_planner_meta";
|
|
333
349
|
/**
|
|
334
350
|
* Filter for querying tasks.
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import { Document } from 'mongodb';
|
|
2
2
|
import type { Registry } from 'prom-client';
|
|
3
3
|
import { GlobalsCollection } from '../globalsCollection';
|
|
4
|
-
import { OnError } from '../OnError';
|
|
5
|
-
import { OnInfo } from '../OnInfo';
|
|
6
4
|
import { ReactiveTaskManager } from './ReactiveTaskManager';
|
|
7
5
|
import { ReactiveTaskRegistry } from './ReactiveTaskRegistry';
|
|
8
6
|
import { PagedResult, PaginationOptions, ReactiveTask, ReactiveTaskQuery, ReactiveTaskRecord, ReactiveTaskSchedulerOptions } from './ReactiveTaskTypes';
|
|
9
7
|
export { CODE_REACTIVE_TASK_CLEANUP, CODE_REACTIVE_TASK_FAILED, CODE_REACTIVE_TASK_FINISHED, CODE_REACTIVE_TASK_INITIALIZED, CODE_REACTIVE_TASK_LEADER_LOCK_LOST, CODE_REACTIVE_TASK_PLANNER_RECONCILIATION_FINISHED, CODE_REACTIVE_TASK_PLANNER_RECONCILIATION_STARTED, CODE_REACTIVE_TASK_PLANNER_STARTED, CODE_REACTIVE_TASK_PLANNER_STOPPED, CODE_REACTIVE_TASK_PLANNER_STREAM_ERROR, CODE_REACTIVE_TASK_STARTED, PagedResult, PaginationOptions, ReactiveTask, ReactiveTaskCaller, ReactiveTaskFilter, ReactiveTaskHandler, ReactiveTaskQuery, ReactiveTaskRecord, ReactiveTaskSchedulerOptions, ReactiveTaskStatus, REACTIVE_TASK_META_DOC_ID, TaskConditionFailedError, } from './ReactiveTaskTypes';
|
|
10
8
|
export { scheduler as _scheduler };
|
|
11
9
|
export type InitOptions = {
|
|
12
|
-
onError: OnError;
|
|
13
|
-
onInfo: OnInfo;
|
|
14
10
|
globalsCollection: GlobalsCollection;
|
|
15
11
|
} & Partial<ReactiveTaskSchedulerOptions>;
|
|
16
12
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactiveTaskScheduler } from '../reactiveTasks/index';
|
|
2
|
-
import { CronTaskQuery } from '../cronTasks';
|
|
3
2
|
import { Document } from 'mongodb';
|
|
3
|
+
import { CronTaskQuery } from '../cronTasks';
|
|
4
4
|
export declare class OperationalTaskController {
|
|
5
5
|
private scheduler;
|
|
6
6
|
constructor(scheduler: ReactiveTaskScheduler);
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import { ObjectId } from 'mongodb';
|
|
2
|
-
import { OnError } from './OnError';
|
|
3
|
-
export declare function init(options: {
|
|
4
|
-
onError: OnError;
|
|
5
|
-
}): void;
|
|
6
2
|
export type LockKey = string | number | ObjectId;
|
|
7
3
|
export type LockCallback<T> = () => Promise<T>;
|
|
8
4
|
export type WithLockOptions = {
|
|
@@ -10,9 +6,10 @@ export type WithLockOptions = {
|
|
|
10
6
|
startingDelay?: number;
|
|
11
7
|
expireIn?: number;
|
|
12
8
|
};
|
|
9
|
+
export declare function reset(): void;
|
|
13
10
|
export declare class LockAlreadyAcquiredError extends Error {
|
|
14
11
|
readonly key: LockKey;
|
|
15
12
|
constructor(key: LockKey);
|
|
16
13
|
}
|
|
17
14
|
export declare function isLockAlreadyAcquiredError(err: unknown, key?: LockKey): boolean;
|
|
18
|
-
export declare function withLock<T>(key: LockKey, callback: LockCallback<T>,
|
|
15
|
+
export declare function withLock<T>(key: LockKey, callback: LockCallback<T>, options?: WithLockOptions): Promise<T>;
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import { ClientSession
|
|
2
|
-
import { OnError } from './OnError';
|
|
3
|
-
import { OnInfo } from './OnInfo';
|
|
4
|
-
export type InitOptions = {
|
|
5
|
-
onError: OnError;
|
|
6
|
-
onInfo: OnInfo;
|
|
7
|
-
};
|
|
1
|
+
import { ClientSession } from 'mongodb';
|
|
8
2
|
export type PostCommitHook = () => void | Promise<void>;
|
|
9
|
-
export declare function init(options: InitOptions): void;
|
|
10
3
|
export declare function registerPostCommitHook(session: ClientSession, hook: PostCommitHook): void;
|
|
11
|
-
export declare function withTransaction<T>(callback: (session: ClientSession) => Promise<T
|
|
4
|
+
export declare function withTransaction<T>(callback: (session: ClientSession) => Promise<T>): Promise<T>;
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
"hash": "
|
|
2
|
+
"hash": "65ae190e",
|
|
3
3
|
"configHash": "1734f516",
|
|
4
|
-
"lockfileHash": "
|
|
5
|
-
"browserHash": "
|
|
4
|
+
"lockfileHash": "68b03582",
|
|
5
|
+
"browserHash": "246dbe54",
|
|
6
6
|
"optimized": {
|
|
7
7
|
"vue": {
|
|
8
8
|
"src": "../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
|
|
9
9
|
"file": "vue.js",
|
|
10
|
-
"fileHash": "
|
|
10
|
+
"fileHash": "1ab8f95b",
|
|
11
11
|
"needsInterop": false
|
|
12
12
|
},
|
|
13
13
|
"vitepress > @vue/devtools-api": {
|
|
14
14
|
"src": "../../../../node_modules/@vue/devtools-api/dist/index.js",
|
|
15
15
|
"file": "vitepress___@vue_devtools-api.js",
|
|
16
|
-
"fileHash": "
|
|
16
|
+
"fileHash": "eb38336e",
|
|
17
17
|
"needsInterop": false
|
|
18
18
|
},
|
|
19
19
|
"vitepress > @vueuse/core": {
|
|
20
20
|
"src": "../../../../node_modules/@vueuse/core/index.mjs",
|
|
21
21
|
"file": "vitepress___@vueuse_core.js",
|
|
22
|
-
"fileHash": "
|
|
22
|
+
"fileHash": "d06fa19f",
|
|
23
23
|
"needsInterop": false
|
|
24
24
|
}
|
|
25
25
|
},
|
|
@@ -36,7 +36,7 @@ export default defineConfig({
|
|
|
36
36
|
{ text: 'Configuration', link: '/reactive-tasks/configuration' },
|
|
37
37
|
{ text: 'Retry Policy', link: '/reactive-tasks/policy-retry' },
|
|
38
38
|
{ text: 'Cleanup Policy', link: '/reactive-tasks/policy-cleanup' },
|
|
39
|
-
{ text: '
|
|
39
|
+
{ text: 'Task Evolution', link: '/reactive-tasks/evolution' },
|
|
40
40
|
{ text: 'Reconciliation', link: '/reactive-tasks/reconciliation' },
|
|
41
41
|
{ text: 'Task Management & DLQ', link: '/reactive-tasks/management' },
|
|
42
42
|
{ text: 'Monitoring', link: '/reactive-tasks/monitoring' },
|
|
@@ -25,7 +25,7 @@ you can use the following options:
|
|
|
25
25
|
| `retryPolicy` | `RetryPolicy` | Configuration for retries on failure. See [Retry Policy](./policy-retry.md). |
|
|
26
26
|
| `cleanupPolicy` | `CleanupPolicy` | Configuration for automatic cleanup of orphaned task records. See [Cleanup Policy](./policy-cleanup.md). |
|
|
27
27
|
| `executionHistoryLimit` | `number` | Number of past execution entries to keep in `_tasks` doc. Default: `5`. |
|
|
28
|
-
| `evolution` | `EvolutionConfig` | Configuration for handling task logic updates (versioning, reconciliation policies). See [
|
|
28
|
+
| `evolution` | `EvolutionConfig` | Configuration for handling task logic updates (versioning, reconciliation policies). See [Task Evolution](./evolution.md). |
|
|
29
29
|
|
|
30
30
|
## Advanced Initialization
|
|
31
31
|
|
|
@@ -41,6 +41,8 @@ To ensure reliability and efficiency, the system needs to determine *when* to tr
|
|
|
41
41
|
watchProjection: { updatedAt: 1 }
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
|
|
45
|
+
|
|
44
46
|
## Task Lifecycle (States)
|
|
45
47
|
|
|
46
48
|
Every task record in the `_tasks` collection follows a specific lifecycle:
|
|
@@ -56,3 +58,20 @@ Every task record in the `_tasks` collection follows a specific lifecycle:
|
|
|
56
58
|
|
|
57
59
|
|
|
58
60
|
|
|
61
|
+
|
|
62
|
+
## Task Schema
|
|
63
|
+
|
|
64
|
+
Each reactive task is stored as a document in the `[collection]_tasks` collection. Key fields include:
|
|
65
|
+
|
|
66
|
+
- `task`: The task name.
|
|
67
|
+
- `sourceDocId`: The `_id` of the source document.
|
|
68
|
+
- `status`: Current state (`pending`, `processing`, `completed`, `failed`).
|
|
69
|
+
- `nextRunAt`: **Core Scheduling Field**.
|
|
70
|
+
- For `pending` tasks: The time when the task is eligible to run (includes delays/backoff).
|
|
71
|
+
- For `processing` tasks: The time when the processing lock expires (visibility timeout).
|
|
72
|
+
- For `completed`/`failed` tasks: `null` (removed from the polling index).
|
|
73
|
+
- `dueAt` (formerly `initialScheduledAt`): The **Original Scheduled Time**.
|
|
74
|
+
- This value is static and represents when the task *should* have run primarily.
|
|
75
|
+
- It is used for calculating **Lag** metrics (SLA monitoring) and does not change during retries or backoffs.
|
|
76
|
+
- `attempts`: Number of execution attempts (including the first one).
|
|
77
|
+
- `lastError`: The error message from the last failure (if any).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Task Evolution
|
|
2
2
|
|
|
3
3
|
Reactive Tasks are designed to evolve with your application. As you deploy new versions of your code, you might change the `filter`, `watchProjection`, or the `handler` logic itself. The system automatically detects these changes and adapts the task state accordingly.
|
|
4
4
|
|
|
@@ -1,24 +1,64 @@
|
|
|
1
1
|
# Guides & Patterns
|
|
2
2
|
|
|
3
|
+
## Understanding Logic: Filter vs WatchProjection
|
|
4
|
+
|
|
5
|
+
It is important to understand the relationship between `filter` and `watchProjection`. You can think of them as **"The Gatekeeper"** and **"The Trigger"**.
|
|
6
|
+
|
|
7
|
+
### 1. `filter` (The Gatekeeper)
|
|
8
|
+
Decides **IF** the task should exist at all.
|
|
9
|
+
- **Enters Filter**: If a document changes to match the filter (e.g., `status` changes from `'pending'` -> `'paid'`), the task is **created and runs immediately**, regardless of `watchProjection`.
|
|
10
|
+
- **Leaves Filter**: If a document changes to no longer match (e.g., `'paid'` -> `'cancelled'`), the task is **removed/cleaned up** (depending on your [Cleanup Policy](./policy-cleanup.md)).
|
|
11
|
+
|
|
12
|
+
### 2. `watchProjection` (The Trigger)
|
|
13
|
+
Decides **WHEN** to re-run the task *if it already exists*.
|
|
14
|
+
- Once the task matches the filter and is active, `watchProjection` determines which future updates matter.
|
|
15
|
+
- **Example**: You have a task to sync paid orders to ERP.
|
|
16
|
+
```typescript
|
|
17
|
+
{
|
|
18
|
+
filter: { status: 'paid' },
|
|
19
|
+
watchProjection: { status: 1 } // Only watch status
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
- **Scenario**: User updates `shippingAddress` on a `paid` order.
|
|
23
|
+
- **Result**: The system sees `status` didn't change (still `'paid'`). It **IGNORES** the address update. The ERP sync **does not re-run** (potentially leaving ERP with stale address).
|
|
24
|
+
- **Fix**: If you need to re-sync on address changes, include `shippingAddress` in `watchProjection` (or omit it to watch everything).
|
|
25
|
+
|
|
26
|
+
> [!TIP]
|
|
27
|
+
> **Best Practice**: If you use a field in `filter` (like `status: 'paid'`), you implicitly don't need to put it in `watchProjection` unless the value can change while remaining valid (e.g., `amount > 100`). However, adding it is harmless and can improve clarity and storage efficiency.
|
|
28
|
+
|
|
29
|
+
## Execution Model & Guarantees
|
|
30
|
+
|
|
31
|
+
The system follows a **Reactive (State-Based)** execution model. It prioritizes **Eventual Consistency** over strict event logging.
|
|
3
32
|
|
|
33
|
+
### 1. State-Based Consistency (vs. Event-Based)
|
|
4
34
|
|
|
5
|
-
|
|
35
|
+
Unlike an Event Bus (e.g., Kafka) that processes every single state transition log, this library guarantees that the **current state** of the document will consistently match your task logic.
|
|
6
36
|
|
|
7
|
-
|
|
37
|
+
* **Transient States are Skipped**: If a document changes state multiple times rapidly (e.g., `pending` -> `paid` -> `refunded` in milliseconds), the system may skip processing the intermediate `paid` state if it is no longer valid by the time the worker picks it up.
|
|
38
|
+
* **Late Binding Check**: This is enforced via a runtime check (`getDocument`). If the fetched document no longer matches the task filter or the watched fields have changed since triggering, the task for the "stale" version is skipped. This is a feature (Optimistic Concurrency) to prevent processing obsolete data.
|
|
8
39
|
|
|
9
|
-
|
|
40
|
+
### 2. At-Least-Once Guarantee (Final State)
|
|
10
41
|
|
|
11
|
-
|
|
42
|
+
The system guarantees that the **final, stable state** of a document will strictly be processed **at least once**.
|
|
43
|
+
If a worker crashes, loses network, or restarts *before* successfully completing a task (and releasing the lock), the task remains `pending`. Another worker will pick it up and retry execution.
|
|
44
|
+
|
|
45
|
+
### 3. Idempotency Requirement
|
|
46
|
+
|
|
47
|
+
Because of the "At-Least-Once" guarantee, **your `handler` must be idempotent**.
|
|
48
|
+
This means it should be safe to run the same handler multiple times for the same document without producing incorrect side effects (like sending duplicate emails or charging a card twice).
|
|
49
|
+
|
|
50
|
+
#### Common Re-execution Scenarios
|
|
12
51
|
|
|
13
52
|
1. **Transient Failures ([Retries](./policy-retry.md))**: If a worker crashes or loses network connectivity during execution (before marking the task `completed`), the lock will expire. Another worker will pick up the task and retry it.
|
|
14
53
|
2. **[Reconciliation](./reconciliation.md) Recovery**: If task records are deleted (e.g. manual cleanup) but source documents remain, once a reconciliation runs, it recreates them as `pending`.
|
|
15
|
-
3. **Filter Re-matching
|
|
16
|
-
4. **Explicit Reprocessing**: You might trigger re-execution manually (via `retryReactiveTasks`) or through [
|
|
54
|
+
3. **Filter Re-matching**: If a document is no longer matching the task filter, the task is deleted because the **[sourceDocumentDeletedOrNoLongerMatching](./policy-cleanup.md)** cleanup policy is used and then the document is changed back again to match the task filter, the task will be recreated as `pending`.
|
|
55
|
+
4. **Explicit Reprocessing**: You might trigger re-execution manually (via `retryReactiveTasks`) or through [Task Evolution policies](./evolution.md) (`reprocess_all`).
|
|
17
56
|
|
|
18
|
-
|
|
57
|
+
#### Designing Idempotent Handlers
|
|
19
58
|
|
|
20
59
|
Ensure your handler allows multiple executions without adverse side effects.
|
|
21
60
|
|
|
61
|
+
|
|
22
62
|
**Example**:
|
|
23
63
|
```typescript
|
|
24
64
|
handler: async (context) => {
|