mongodash 2.0.0 → 2.1.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/README.md +40 -22
- package/dist/dashboard/index.html +40 -0
- package/dist/lib/playground/server.js +131 -0
- package/dist/lib/playground/server.js.map +1 -0
- package/dist/lib/src/ConcurrentRunner.js +148 -0
- package/dist/lib/src/ConcurrentRunner.js.map +1 -0
- package/dist/lib/{OnError.js → src/OnError.js} +3 -3
- package/dist/lib/src/OnError.js.map +1 -0
- package/dist/lib/{OnInfo.js → src/OnInfo.js} +6 -3
- package/dist/lib/src/OnInfo.js.map +1 -0
- package/dist/lib/{createContinuousLock.js → src/createContinuousLock.js} +5 -3
- package/dist/lib/src/createContinuousLock.js.map +1 -0
- package/dist/lib/{cronTasks.js → src/cronTasks.js} +129 -73
- package/dist/lib/src/cronTasks.js.map +1 -0
- package/dist/lib/{getCollection.js → src/getCollection.js} +2 -2
- package/dist/lib/src/getCollection.js.map +1 -0
- package/dist/lib/{getMongoClient.js → src/getMongoClient.js} +2 -2
- package/dist/lib/src/getMongoClient.js.map +1 -0
- package/dist/lib/src/globalsCollection.js +10 -0
- package/dist/lib/src/globalsCollection.js.map +1 -0
- package/dist/lib/src/index.js +101 -0
- package/dist/lib/src/index.js.map +1 -0
- package/dist/lib/{initPromise.js → src/initPromise.js} +2 -3
- package/dist/lib/src/initPromise.js.map +1 -0
- package/dist/lib/src/mongoCompatibility.js +10 -0
- package/dist/lib/src/mongoCompatibility.js.map +1 -0
- package/dist/lib/src/parseInterval.js +60 -0
- package/dist/lib/src/parseInterval.js.map +1 -0
- package/dist/lib/src/prefixFilterKeys.js +69 -0
- package/dist/lib/src/prefixFilterKeys.js.map +1 -0
- package/dist/lib/src/processInBatches.js +46 -0
- package/dist/lib/src/processInBatches.js.map +1 -0
- package/dist/lib/src/reactiveTasks/LeaderElector.js +155 -0
- package/dist/lib/src/reactiveTasks/LeaderElector.js.map +1 -0
- package/dist/lib/src/reactiveTasks/MetricsCollector.js +410 -0
- package/dist/lib/src/reactiveTasks/MetricsCollector.js.map +1 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskManager.js +288 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskManager.js.map +1 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskOps.js +185 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskOps.js.map +1 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskPlanner.js +443 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskPlanner.js.map +1 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskReconciler.js +218 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskReconciler.js.map +1 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskRegistry.js +184 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskRegistry.js.map +1 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskRepository.js +355 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskRepository.js.map +1 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskRetryStrategy.js +153 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskRetryStrategy.js.map +1 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskTypes.js +34 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskTypes.js.map +1 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskWorker.js +186 -0
- package/dist/lib/src/reactiveTasks/ReactiveTaskWorker.js.map +1 -0
- package/dist/lib/src/reactiveTasks/compileWatchProjection.js +65 -0
- package/dist/lib/src/reactiveTasks/compileWatchProjection.js.map +1 -0
- package/dist/lib/src/reactiveTasks/index.js +298 -0
- package/dist/lib/src/reactiveTasks/index.js.map +1 -0
- package/dist/lib/src/reactiveTasks/queryToExpression.js +160 -0
- package/dist/lib/src/reactiveTasks/queryToExpression.js.map +1 -0
- package/dist/lib/src/reactiveTasks/validateTaskFilter.js +88 -0
- package/dist/lib/src/reactiveTasks/validateTaskFilter.js.map +1 -0
- package/dist/lib/src/task-management/OperationalTaskController.js +162 -0
- package/dist/lib/src/task-management/OperationalTaskController.js.map +1 -0
- package/dist/lib/src/task-management/index.js +27 -0
- package/dist/lib/src/task-management/index.js.map +1 -0
- package/dist/lib/src/task-management/serveDashboard.js +149 -0
- package/dist/lib/src/task-management/serveDashboard.js.map +1 -0
- package/dist/lib/src/task-management/types.js +10 -0
- package/dist/lib/src/task-management/types.js.map +1 -0
- package/dist/lib/{withLock.js → src/withLock.js} +3 -4
- package/dist/lib/src/withLock.js.map +1 -0
- package/dist/lib/{withTransaction.js → src/withTransaction.js} +4 -4
- package/dist/lib/src/withTransaction.js.map +1 -0
- package/dist/lib/tools/check-db-connection.js +28 -0
- package/dist/lib/tools/check-db-connection.js.map +1 -0
- package/dist/lib/tools/clean-testing-databases.js +12 -0
- package/dist/lib/tools/clean-testing-databases.js.map +1 -0
- package/dist/lib/tools/prepare-republish.js +27 -0
- package/dist/lib/tools/prepare-republish.js.map +1 -0
- package/dist/lib/tools/test-matrix-local.js +212 -0
- package/dist/lib/tools/test-matrix-local.js.map +1 -0
- package/dist/lib/tools/testingDatabase.js +55 -0
- package/dist/lib/tools/testingDatabase.js.map +1 -0
- package/dist/types/playground/server.d.ts +1 -0
- package/dist/types/src/ConcurrentRunner.d.ts +30 -0
- package/dist/types/{OnInfo.d.ts → src/OnInfo.d.ts} +1 -1
- package/dist/types/{cronTasks.d.ts → src/cronTasks.d.ts} +44 -1
- package/dist/types/src/globalsCollection.d.ts +4 -0
- package/dist/types/src/index.d.ts +28 -0
- package/dist/types/src/mongoCompatibility.d.ts +29 -0
- package/dist/types/src/parseInterval.d.ts +12 -0
- package/dist/types/src/prefixFilterKeys.d.ts +11 -0
- package/dist/types/src/processInBatches.d.ts +10 -0
- package/dist/types/src/reactiveTasks/LeaderElector.d.ts +42 -0
- package/dist/types/src/reactiveTasks/MetricsCollector.d.ts +73 -0
- package/dist/types/src/reactiveTasks/ReactiveTaskManager.d.ts +18 -0
- package/dist/types/src/reactiveTasks/ReactiveTaskOps.d.ts +17 -0
- package/dist/types/src/reactiveTasks/ReactiveTaskPlanner.d.ts +62 -0
- package/dist/types/src/reactiveTasks/ReactiveTaskReconciler.d.ts +29 -0
- package/dist/types/src/reactiveTasks/ReactiveTaskRegistry.d.ts +34 -0
- package/dist/types/src/reactiveTasks/ReactiveTaskRepository.d.ts +59 -0
- package/dist/types/src/reactiveTasks/ReactiveTaskRetryStrategy.d.ts +21 -0
- package/dist/types/src/reactiveTasks/ReactiveTaskTypes.d.ts +389 -0
- package/dist/types/src/reactiveTasks/ReactiveTaskWorker.d.ts +36 -0
- package/dist/types/src/reactiveTasks/compileWatchProjection.d.ts +12 -0
- package/dist/types/src/reactiveTasks/index.d.ts +82 -0
- package/dist/types/src/reactiveTasks/queryToExpression.d.ts +13 -0
- package/dist/types/src/reactiveTasks/validateTaskFilter.d.ts +10 -0
- package/dist/types/src/task-management/OperationalTaskController.d.ts +59 -0
- package/dist/types/src/task-management/index.d.ts +3 -0
- package/dist/types/src/task-management/serveDashboard.d.ts +12 -0
- package/dist/types/src/task-management/types.d.ts +95 -0
- package/dist/types/tools/check-db-connection.d.ts +2 -0
- package/dist/types/tools/clean-testing-databases.d.ts +1 -0
- package/dist/types/tools/prepare-republish.d.ts +2 -0
- package/dist/types/tools/test-matrix-local.d.ts +1 -0
- package/dist/types/tools/testingDatabase.d.ts +2 -0
- package/docs/.vitepress/cache/deps/_metadata.json +31 -0
- package/docs/.vitepress/cache/deps/chunk-LE5NDSFD.js +12824 -0
- package/docs/.vitepress/cache/deps/chunk-LE5NDSFD.js.map +7 -0
- package/docs/.vitepress/cache/deps/package.json +3 -0
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +4505 -0
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +9731 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
- package/docs/.vitepress/cache/deps/vue.js +347 -0
- package/docs/.vitepress/cache/deps/vue.js.map +7 -0
- package/docs/.vitepress/config.mts +48 -0
- package/docs/.vitepress/theme/index.ts +4 -0
- package/docs/.vitepress/theme/style.css +16 -0
- package/docs/assets/dashboard.png +0 -0
- package/docs/cron-tasks.md +172 -0
- package/docs/dashboard.md +117 -0
- package/docs/getters.md +31 -0
- package/docs/getting-started.md +120 -0
- package/docs/index.md +29 -0
- package/docs/initialization.md +59 -0
- package/docs/process-in-batches.md +73 -0
- package/docs/reactive-tasks.md +914 -0
- package/docs/with-lock.md +45 -0
- package/docs/with-transaction.md +65 -0
- package/grafana/reactive_tasks.json +765 -0
- package/package.json +127 -116
- package/dist/lib/OnError.js.map +0 -1
- package/dist/lib/OnInfo.js.map +0 -1
- package/dist/lib/createContinuousLock.js.map +0 -1
- package/dist/lib/cronTasks.js.map +0 -1
- package/dist/lib/getCollection.js.map +0 -1
- package/dist/lib/getMongoClient.js.map +0 -1
- package/dist/lib/index.js +0 -64
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/initPromise.js.map +0 -1
- package/dist/lib/withLock.js.map +0 -1
- package/dist/lib/withTransaction.js.map +0 -1
- package/dist/types/index.d.ts +0 -17
- /package/dist/types/{OnError.d.ts → src/OnError.d.ts} +0 -0
- /package/dist/types/{createContinuousLock.d.ts → src/createContinuousLock.d.ts} +0 -0
- /package/dist/types/{getCollection.d.ts → src/getCollection.d.ts} +0 -0
- /package/dist/types/{getMongoClient.d.ts → src/getMongoClient.d.ts} +0 -0
- /package/dist/types/{initPromise.d.ts → src/initPromise.d.ts} +0 -0
- /package/dist/types/{withLock.d.ts → src/withLock.d.ts} +0 -0
- /package/dist/types/{withTransaction.d.ts → src/withTransaction.d.ts} +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { GlobalsCollection } from '../globalsCollection';
|
|
2
|
+
import { OnInfo } from '../OnInfo';
|
|
3
|
+
import { OnError } from '../OnError';
|
|
4
|
+
export interface LeaderElectorCallbacks {
|
|
5
|
+
onBecomeLeader: () => Promise<void>;
|
|
6
|
+
onLoseLeader: () => Promise<void>;
|
|
7
|
+
onHeartbeat: () => Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface LeaderElectorOptions {
|
|
10
|
+
lockTtlMs: number;
|
|
11
|
+
lockHeartbeatMs: number;
|
|
12
|
+
metaDocId?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Manages leader election among multiple scheduler instances.
|
|
16
|
+
*
|
|
17
|
+
* Responsibilities:
|
|
18
|
+
* - Attempts to acquire a distributed lock in the globals collection.
|
|
19
|
+
* - Maintains the lock by periodically renewing it (heartbeat).
|
|
20
|
+
* - Notifies callbacks when the instance becomes leader or loses leadership.
|
|
21
|
+
* - Ensures only one instance (the leader) runs the `ReactiveTaskPlanner` at a time.
|
|
22
|
+
*/
|
|
23
|
+
export declare class LeaderElector {
|
|
24
|
+
private globalsCollection;
|
|
25
|
+
private instanceId;
|
|
26
|
+
private options;
|
|
27
|
+
private callbacks;
|
|
28
|
+
private onInfo;
|
|
29
|
+
private onError;
|
|
30
|
+
private isRunning;
|
|
31
|
+
private _isLeader;
|
|
32
|
+
private leaderTimer;
|
|
33
|
+
private metaDocId;
|
|
34
|
+
constructor(globalsCollection: GlobalsCollection, instanceId: string, options: LeaderElectorOptions, callbacks: LeaderElectorCallbacks, onInfo?: OnInfo, onError?: OnError);
|
|
35
|
+
get isLeader(): boolean;
|
|
36
|
+
start(): Promise<void>;
|
|
37
|
+
stop(): Promise<void>;
|
|
38
|
+
forceLoseLeader(): void;
|
|
39
|
+
private runLeaderElectionLoop;
|
|
40
|
+
private tryAcquireLock;
|
|
41
|
+
private releaseLock;
|
|
42
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Registry } from 'prom-client';
|
|
2
|
+
import { GlobalsCollection } from '../globalsCollection';
|
|
3
|
+
import { OnError } from '../OnError';
|
|
4
|
+
import { OnInfo } from '../OnInfo';
|
|
5
|
+
import { LeaderElector } from './LeaderElector';
|
|
6
|
+
import { ReactiveTaskPlanner } from './ReactiveTaskPlanner';
|
|
7
|
+
import { ReactiveTaskRegistry } from './ReactiveTaskRegistry';
|
|
8
|
+
import { ReactiveTaskSchedulerOptions } from './ReactiveTaskTypes';
|
|
9
|
+
/**
|
|
10
|
+
* Collects and aggregates metrics for Reactive Tasks.
|
|
11
|
+
*
|
|
12
|
+
* Supports two scrape modes:
|
|
13
|
+
* - **cluster**: Returns aggregated metrics from ALL instances (via DB registry).
|
|
14
|
+
* Use when Prometheus scrapes a single endpoint (e.g., behind a load balancer).
|
|
15
|
+
* - **local**: Returns metrics from THIS instance only.
|
|
16
|
+
* Use when Prometheus scrapes each pod individually (K8s Pod Monitors).
|
|
17
|
+
*
|
|
18
|
+
* Global stats (queue depth, lag) are computed on-the-fly by the **Leader only**.
|
|
19
|
+
*/
|
|
20
|
+
export declare class MetricsCollector {
|
|
21
|
+
private enabled;
|
|
22
|
+
private readonly options;
|
|
23
|
+
private readonly instanceId;
|
|
24
|
+
private readonly registry;
|
|
25
|
+
private readonly globalsCollection;
|
|
26
|
+
private readonly leaderElector;
|
|
27
|
+
private readonly onInfo;
|
|
28
|
+
private readonly onError;
|
|
29
|
+
private promClientModule;
|
|
30
|
+
private localPromRegistry?;
|
|
31
|
+
private globalStatsRegistry?;
|
|
32
|
+
private metricDuration?;
|
|
33
|
+
private metricRetries?;
|
|
34
|
+
private pushInterval?;
|
|
35
|
+
private queueMetricsPromise;
|
|
36
|
+
planner?: ReactiveTaskPlanner;
|
|
37
|
+
constructor(instanceId: string, registry: ReactiveTaskRegistry, globalsCollection: GlobalsCollection, leaderElector: LeaderElector, options: ReactiveTaskSchedulerOptions['monitoring'], onInfo?: OnInfo, onError?: OnError);
|
|
38
|
+
private initPrometheus;
|
|
39
|
+
private initLocalMetrics;
|
|
40
|
+
private initGlobalStatsMetrics;
|
|
41
|
+
start(): void;
|
|
42
|
+
stop(): void;
|
|
43
|
+
recordTaskExecution(task: string, status: 'success' | 'failed', durationMs: number): void;
|
|
44
|
+
recordRetry(task: string): void;
|
|
45
|
+
getPrometheusMetrics(): Promise<Registry | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Returns aggregated metrics from ALL instances.
|
|
48
|
+
* Fetches other instances' metrics from DB and merges with fresh local metrics.
|
|
49
|
+
* Leader also includes global stats.
|
|
50
|
+
*/
|
|
51
|
+
private getClusterMetrics;
|
|
52
|
+
/**
|
|
53
|
+
* Returns metrics from THIS instance only.
|
|
54
|
+
* Leader also includes global stats.
|
|
55
|
+
*/
|
|
56
|
+
private getLocalMetrics;
|
|
57
|
+
private fetchOtherInstancesMetrics;
|
|
58
|
+
private getLocalMetricsAsJson;
|
|
59
|
+
private getGlobalStatsAsJson;
|
|
60
|
+
private triggerGlobalStatsCollection;
|
|
61
|
+
private pushLocalMetrics;
|
|
62
|
+
private publishMetricsToGlobalRegistry;
|
|
63
|
+
private collectIfLeader;
|
|
64
|
+
/**
|
|
65
|
+
* Triggers queue metrics collection with deduplication.
|
|
66
|
+
* Both QUEUE_DEPTH and GLOBAL_LAG share the same aggregation query.
|
|
67
|
+
*/
|
|
68
|
+
private triggerQueueMetricsCollection;
|
|
69
|
+
private collectQueueMetrics;
|
|
70
|
+
private collectReconciliationMetrics;
|
|
71
|
+
private collectChangeStreamLag;
|
|
72
|
+
private getOrCreateMetric;
|
|
73
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Document } from 'mongodb';
|
|
2
|
+
import { ReactiveTaskRegistry } from './ReactiveTaskRegistry';
|
|
3
|
+
import { PagedResult, PaginationOptions, ReactiveTaskQuery, ReactiveTaskRecord, ReactiveTaskStatsResult } from './ReactiveTaskTypes';
|
|
4
|
+
export declare class ReactiveTaskManager {
|
|
5
|
+
private registry;
|
|
6
|
+
constructor(registry: ReactiveTaskRegistry);
|
|
7
|
+
getTasks(query: ReactiveTaskQuery<Document>, pagination?: PaginationOptions): Promise<PagedResult<ReactiveTaskRecord<Document>>>;
|
|
8
|
+
countTasks(query: ReactiveTaskQuery<Document>): Promise<number>;
|
|
9
|
+
getAllTaskStats(): Promise<Record<string, ReactiveTaskStatsResult>>;
|
|
10
|
+
getTaskStats(query: ReactiveTaskQuery<Document>): Promise<ReactiveTaskStatsResult>;
|
|
11
|
+
retryTasks(query: ReactiveTaskQuery<Document>): Promise<{
|
|
12
|
+
modifiedCount: number;
|
|
13
|
+
}>;
|
|
14
|
+
private resolveTaskNames;
|
|
15
|
+
private resolveCollectionsAndQueries;
|
|
16
|
+
private buildDirectQuery;
|
|
17
|
+
private isComplexSourceFilter;
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ReactiveTaskRegistry } from './ReactiveTaskRegistry';
|
|
2
|
+
/**
|
|
3
|
+
* Helper class for generating and executing reactive task operations.
|
|
4
|
+
*
|
|
5
|
+
* Responsibilities:
|
|
6
|
+
* - Generates upsert operations for tasks based on source documents and task definitions.
|
|
7
|
+
* - Executes bulk write operations to the task collections.
|
|
8
|
+
* - Handles duplicate key errors gracefully (which can occur during reconciliation).
|
|
9
|
+
* - Manages debouncing logic by tracking the minimum debounce time for planned tasks.
|
|
10
|
+
*/
|
|
11
|
+
export declare class ReactiveTaskOps {
|
|
12
|
+
private registry;
|
|
13
|
+
private onTaskPlanned;
|
|
14
|
+
constructor(registry: ReactiveTaskRegistry, onTaskPlanned: (tasksCollectionName: string, debounceMs: number) => void);
|
|
15
|
+
executePlanningPipeline(collectionName: string, sourceDocIds: unknown[], allowedTaskNames?: Set<string>): Promise<void>;
|
|
16
|
+
private generatePlanningPipeline;
|
|
17
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ResumeToken } from 'mongodb';
|
|
2
|
+
import { GlobalsCollection } from '../globalsCollection';
|
|
3
|
+
import { ReactiveTaskRegistry } from './ReactiveTaskRegistry';
|
|
4
|
+
import { OnInfo } from '../OnInfo';
|
|
5
|
+
import { OnError } from '../OnError';
|
|
6
|
+
export interface PlannerCallbacks {
|
|
7
|
+
onStreamError: () => void;
|
|
8
|
+
onTaskPlanned: (tasksCollectionName: string, debounceMs: number) => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Responsible for listening to MongoDB Change Stream events and planning tasks.
|
|
12
|
+
*
|
|
13
|
+
* Responsibilities:
|
|
14
|
+
* - Manages the lifecycle of the Change Stream (start, stop, error handling).
|
|
15
|
+
* - Batches Change Stream events to reduce database load.
|
|
16
|
+
* - Coordinates with `ReactiveTaskOps` to generate and execute task operations.
|
|
17
|
+
* - Coordinates with `ReactiveTaskReconciler` to handle reconciliation when the stream is interrupted or history is lost.
|
|
18
|
+
* - Handles critical errors like `ChangeStreamHistoryLost` (code 280) by triggering reconciliation.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ReactiveTaskPlanner {
|
|
21
|
+
private globalsCollection;
|
|
22
|
+
private instanceId;
|
|
23
|
+
private registry;
|
|
24
|
+
private callbacks;
|
|
25
|
+
private internalOptions;
|
|
26
|
+
private onInfo;
|
|
27
|
+
private onError;
|
|
28
|
+
private changeStream;
|
|
29
|
+
private taskBatch;
|
|
30
|
+
private taskBatchLastResumeToken;
|
|
31
|
+
private batchFlushTimer;
|
|
32
|
+
private isFlushing;
|
|
33
|
+
private metaDocId;
|
|
34
|
+
private lastClusterTime;
|
|
35
|
+
private ops;
|
|
36
|
+
private reconciler;
|
|
37
|
+
private get isStoppedTester();
|
|
38
|
+
constructor(globalsCollection: GlobalsCollection, instanceId: string, registry: ReactiveTaskRegistry, callbacks: PlannerCallbacks, internalOptions: {
|
|
39
|
+
batchSize: number;
|
|
40
|
+
batchIntervalMs: number;
|
|
41
|
+
getNextCleanupDate: (date?: Date) => Date;
|
|
42
|
+
}, onInfo?: OnInfo, onError?: OnError);
|
|
43
|
+
start(): Promise<void>;
|
|
44
|
+
stop(): Promise<void>;
|
|
45
|
+
saveResumeToken(token: ResumeToken, lastClusterTime?: Date): Promise<void>;
|
|
46
|
+
get isEmpty(): boolean;
|
|
47
|
+
onHeartbeat(): Promise<void>;
|
|
48
|
+
private isStopping;
|
|
49
|
+
private startChangeStream;
|
|
50
|
+
private stopChangeStream;
|
|
51
|
+
private getChangeStreamPipeline;
|
|
52
|
+
private getChangeStreamResumeToken;
|
|
53
|
+
private enqueueTaskChange;
|
|
54
|
+
private flushTaskBatch;
|
|
55
|
+
private groupEventsByCollection;
|
|
56
|
+
private processDeletions;
|
|
57
|
+
private executeUpsertOperations;
|
|
58
|
+
private handleStreamError;
|
|
59
|
+
private checkEvolutionStrategies;
|
|
60
|
+
private checkTriggerEvolution;
|
|
61
|
+
private checkLogicEvolution;
|
|
62
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { GlobalsCollection } from '../globalsCollection';
|
|
2
|
+
import { OnInfo } from '../OnInfo';
|
|
3
|
+
import { ReactiveTaskOps } from './ReactiveTaskOps';
|
|
4
|
+
import { ReactiveTaskRegistry } from './ReactiveTaskRegistry';
|
|
5
|
+
/**
|
|
6
|
+
* Responsible for reconciling reactive tasks when the Change Stream history is lost or on startup.
|
|
7
|
+
*
|
|
8
|
+
* Responsibilities:
|
|
9
|
+
* - Scans source collections to identify tasks that should exist.
|
|
10
|
+
* - Uses `ReactiveTaskOps` to generate and execute task operations.
|
|
11
|
+
* - Tracks reconciliation status in the meta document.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ReactiveTaskReconciler {
|
|
14
|
+
private instanceId;
|
|
15
|
+
private globalsCollection;
|
|
16
|
+
private registry;
|
|
17
|
+
private ops;
|
|
18
|
+
private onInfo;
|
|
19
|
+
private internalOptions;
|
|
20
|
+
constructor(instanceId: string, globalsCollection: GlobalsCollection, registry: ReactiveTaskRegistry, ops: ReactiveTaskOps, onInfo: OnInfo, internalOptions: {
|
|
21
|
+
batchSize: number;
|
|
22
|
+
batchIntervalMs: number;
|
|
23
|
+
getNextCleanupDate: (date?: Date) => Date;
|
|
24
|
+
});
|
|
25
|
+
private nextCleanupTime;
|
|
26
|
+
reconcile(shouldStop: () => boolean): Promise<void>;
|
|
27
|
+
markAsUnreconciled(taskNames: string[]): Promise<void>;
|
|
28
|
+
performPeriodicCleanup(shouldStop: () => boolean): Promise<void>;
|
|
29
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Collection, Document } from 'mongodb';
|
|
2
|
+
import { OnError } from '../OnError';
|
|
3
|
+
import { OnInfo } from '../OnInfo';
|
|
4
|
+
import { ReactiveTaskRepository } from './ReactiveTaskRepository';
|
|
5
|
+
import { ReactiveTask, ReactiveTaskInternal, ReactiveTaskRecord } from './ReactiveTaskTypes';
|
|
6
|
+
export interface TaskMapEntry {
|
|
7
|
+
sourceCollection: Collection<Document>;
|
|
8
|
+
tasks: Map<string, ReactiveTaskInternal<Document>>;
|
|
9
|
+
tasksCollection: Collection<ReactiveTaskRecord<Document>>;
|
|
10
|
+
repository: ReactiveTaskRepository<Document>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Registry for managing reactive task definitions and their associated collections.
|
|
14
|
+
*
|
|
15
|
+
* Responsibilities:
|
|
16
|
+
* - Stores task definitions and maps them to source and task collections.
|
|
17
|
+
* - Initializes the `ReactiveTaskRepository` for each task collection.
|
|
18
|
+
* - Provides lookup methods to retrieve tasks by name or collection.
|
|
19
|
+
* - Ensures task uniqueness and validates configuration.
|
|
20
|
+
*/
|
|
21
|
+
export declare class ReactiveTaskRegistry {
|
|
22
|
+
private map;
|
|
23
|
+
private tasksByIdentifiers;
|
|
24
|
+
private onInfo;
|
|
25
|
+
private onError;
|
|
26
|
+
constructor(onInfo?: OnInfo, onError?: OnError);
|
|
27
|
+
setCallbacks(onInfo: OnInfo, onError: OnError): void;
|
|
28
|
+
addTask(taskDef: ReactiveTask<Document>): Promise<void>;
|
|
29
|
+
getTask(taskName: string): ReactiveTaskInternal<Document> | undefined;
|
|
30
|
+
getAllTasks(): ReactiveTaskInternal<Document>[];
|
|
31
|
+
getEntry(collectionName: string): TaskMapEntry;
|
|
32
|
+
getAllEntries(): TaskMapEntry[];
|
|
33
|
+
private validateEvolutionConfig;
|
|
34
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Collection, Document, Filter, UpdateFilter } from 'mongodb';
|
|
2
|
+
import { CompatibleBulkWriteOptions } from '../mongoCompatibility';
|
|
3
|
+
import { OnError } from '../OnError';
|
|
4
|
+
import { OnInfo } from '../OnInfo';
|
|
5
|
+
import { ReactiveTaskRetryStrategy } from './ReactiveTaskRetryStrategy';
|
|
6
|
+
import { CleanupDeleteWhen, ReactiveTaskInternal, ReactiveTaskRecord, ReactiveTaskStatsOptions, ReactiveTaskStatsResult } from './ReactiveTaskTypes';
|
|
7
|
+
/**
|
|
8
|
+
* Handles all database interactions for reactive tasks.
|
|
9
|
+
*
|
|
10
|
+
* Responsibilities:
|
|
11
|
+
* - Generates MongoDB operations for creating, updating, and deleting tasks.
|
|
12
|
+
* - Manages task state transitions (pending -> processing -> completed/failed).
|
|
13
|
+
* - Implements the locking mechanism for task execution.
|
|
14
|
+
* - Handles task finalization (retries, completion, failure).
|
|
15
|
+
* - Manages database indexes for performance.
|
|
16
|
+
* - Cleans up orphaned tasks.
|
|
17
|
+
*/
|
|
18
|
+
export declare class ReactiveTaskRepository<T extends Document> {
|
|
19
|
+
private tasksCollection;
|
|
20
|
+
private onInfo;
|
|
21
|
+
private onError;
|
|
22
|
+
readonly initPromise: Promise<void>;
|
|
23
|
+
constructor(tasksCollection: Collection<ReactiveTaskRecord<T>>, onInfo?: OnInfo, onError?: OnError);
|
|
24
|
+
findAndLockNextTask(taskDefs: ReactiveTaskInternal<T>[], options: {
|
|
25
|
+
visibilityTimeoutMs: number;
|
|
26
|
+
}): Promise<ReactiveTaskRecord<T> | null>;
|
|
27
|
+
finalizeTask(taskRecord: ReactiveTaskRecord<T>, strategy: ReactiveTaskRetryStrategy, error?: Error, debounceMs?: number, executionStats?: {
|
|
28
|
+
durationMs: number;
|
|
29
|
+
}, executionHistoryLimit?: number): Promise<void>;
|
|
30
|
+
deferTask(taskRecord: ReactiveTaskRecord<T>, delay: number | Date): Promise<void>;
|
|
31
|
+
executeBulkWrite(operations: Parameters<Collection<ReactiveTaskRecord<T>>['bulkWrite']>[0], options?: CompatibleBulkWriteOptions): Promise<void>;
|
|
32
|
+
findTasks(filter: Filter<ReactiveTaskRecord<T>>, options?: {
|
|
33
|
+
limit?: number;
|
|
34
|
+
skip?: number;
|
|
35
|
+
sort?: Record<string, 1 | -1>;
|
|
36
|
+
}): Promise<ReactiveTaskRecord<T>[]>;
|
|
37
|
+
countTasks(filter: Filter<ReactiveTaskRecord<T>>): Promise<number>;
|
|
38
|
+
updateTasks(filter: Filter<ReactiveTaskRecord<T>>, update: UpdateFilter<ReactiveTaskRecord<T>> | Document[]): Promise<{
|
|
39
|
+
matchedCount: number;
|
|
40
|
+
modifiedCount: number;
|
|
41
|
+
}>;
|
|
42
|
+
resetTasks(filter: Filter<ReactiveTaskRecord<T>>): Promise<{
|
|
43
|
+
matchedCount: number;
|
|
44
|
+
modifiedCount: number;
|
|
45
|
+
}>;
|
|
46
|
+
resetTasksForUpgrade(taskName: string, mode: 'failed' | 'all'): Promise<{
|
|
47
|
+
modifiedCount: number;
|
|
48
|
+
}>;
|
|
49
|
+
private ensureIndexes;
|
|
50
|
+
/**
|
|
51
|
+
* Periodically cleans up orphaned tasks that match the cleanupPolicy.
|
|
52
|
+
* This runs on a schedule (e.g. hourly) in the Leader instance.
|
|
53
|
+
*/
|
|
54
|
+
deleteOrphanedTasks(taskName: string, sourceCollectionName: string, taskFilter: Filter<Document>, cleanupPolicy: {
|
|
55
|
+
deleteWhen: CleanupDeleteWhen;
|
|
56
|
+
keepForMs: number;
|
|
57
|
+
}, shouldStop: () => boolean, limitToSourceIds?: unknown[]): Promise<void>;
|
|
58
|
+
getStatistics(filter: Filter<ReactiveTaskRecord<T>>, options: ReactiveTaskStatsOptions): Promise<ReactiveTaskStatsResult>;
|
|
59
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RetryPolicy } from './ReactiveTaskTypes';
|
|
2
|
+
export declare class ReactiveTaskRetryStrategy {
|
|
3
|
+
readonly policy: RetryPolicy;
|
|
4
|
+
constructor(policy: RetryPolicy);
|
|
5
|
+
private validatePolicy;
|
|
6
|
+
private validateDuration;
|
|
7
|
+
/**
|
|
8
|
+
* Calculates the timestamp for the next retry attempt.
|
|
9
|
+
* @param attempts Current number of attempts (will be incremented for next check) called AFTER failure
|
|
10
|
+
* @param lastError Timestamp of the last error or last attempt? No, policies are usually "after X time".
|
|
11
|
+
* For linear/exp/fixed, we add delay to NOW.
|
|
12
|
+
* For Cron, we find next date after NOW.
|
|
13
|
+
*/
|
|
14
|
+
calculateNextRetry(attempts: number): Date;
|
|
15
|
+
/**
|
|
16
|
+
* Determines if the task should be marked as permanently failed.
|
|
17
|
+
* @param attempts Number of attempts consumed so far (including the one that just failed)
|
|
18
|
+
* @param firstErrorAt When the first error in this sequence occurred
|
|
19
|
+
*/
|
|
20
|
+
shouldFail(attempts: number, firstErrorAt?: Date | null): boolean;
|
|
21
|
+
}
|