@neofinancial/chrono 0.4.1-next.0 → 0.5.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.
Files changed (44) hide show
  1. package/README.md +10 -0
  2. package/build/index.d.mts +217 -0
  3. package/build/index.d.ts +217 -4
  4. package/build/index.js +352 -11
  5. package/build/index.js.map +1 -1
  6. package/build/index.mjs +325 -0
  7. package/build/index.mjs.map +1 -0
  8. package/package.json +17 -4
  9. package/build/backoff-strategy.d.ts +0 -64
  10. package/build/backoff-strategy.js +0 -86
  11. package/build/backoff-strategy.js.map +0 -1
  12. package/build/chrono.d.ts +0 -37
  13. package/build/chrono.js +0 -71
  14. package/build/chrono.js.map +0 -1
  15. package/build/datastore.d.ts +0 -63
  16. package/build/datastore.js +0 -10
  17. package/build/datastore.js.map +0 -1
  18. package/build/events.d.ts +0 -16
  19. package/build/events.js +0 -10
  20. package/build/events.js.map +0 -1
  21. package/build/processors/create-processor.d.ts +0 -31
  22. package/build/processors/create-processor.js +0 -11
  23. package/build/processors/create-processor.js.map +0 -1
  24. package/build/processors/events.d.ts +0 -50
  25. package/build/processors/events.js +0 -19
  26. package/build/processors/events.js.map +0 -1
  27. package/build/processors/index.d.ts +0 -3
  28. package/build/processors/index.js +0 -8
  29. package/build/processors/index.js.map +0 -1
  30. package/build/processors/processor.d.ts +0 -7
  31. package/build/processors/processor.js +0 -3
  32. package/build/processors/processor.js.map +0 -1
  33. package/build/processors/simple-processor.d.ts +0 -63
  34. package/build/processors/simple-processor.js +0 -161
  35. package/build/processors/simple-processor.js.map +0 -1
  36. package/build/scheduler.d.ts +0 -9
  37. package/build/scheduler.js +0 -21
  38. package/build/scheduler.js.map +0 -1
  39. package/build/task.d.ts +0 -33
  40. package/build/task.js +0 -10
  41. package/build/task.js.map +0 -1
  42. package/build/utils/promise-utils.d.ts +0 -1
  43. package/build/utils/promise-utils.js +0 -20
  44. package/build/utils/promise-utils.js.map +0 -1
package/build/chrono.js DELETED
@@ -1,71 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Chrono = void 0;
4
- const node_stream_1 = require("node:stream");
5
- const events_1 = require("./events");
6
- const processors_1 = require("./processors");
7
- const promise_utils_1 = require("./utils/promise-utils");
8
- /**
9
- * This is a type that represents the mapping of task kinds to their respective data types.
10
- *
11
- * Eg. shape of the TaskMapping type:
12
- *
13
- * type TaskMapping = {
14
- * "async-messaging": { someField: number };
15
- * "send-email": { url: string };
16
- * };
17
- *
18
- */
19
- class Chrono extends node_stream_1.EventEmitter {
20
- datastore;
21
- processors = new Map();
22
- exitTimeoutMs = 60_000;
23
- constructor(datastore) {
24
- super();
25
- this.datastore = datastore;
26
- }
27
- async start() {
28
- for (const processor of this.processors.values()) {
29
- await processor.start();
30
- }
31
- this.emit(events_1.ChronoEvents.STARTED, { startedAt: new Date() });
32
- }
33
- async stop() {
34
- const stopPromises = Array.from(this.processors.values()).map((processor) => processor.stop());
35
- try {
36
- await (0, promise_utils_1.promiseWithTimeout)(Promise.all(stopPromises), this.exitTimeoutMs);
37
- }
38
- catch (error) {
39
- this.emit(events_1.ChronoEvents.STOP_ABORTED, { error, timestamp: new Date() });
40
- }
41
- }
42
- async scheduleTask(input) {
43
- const task = await this.datastore.schedule({
44
- when: input.when,
45
- kind: input.kind,
46
- data: input.data,
47
- datastoreOptions: input.datastoreOptions,
48
- });
49
- return task;
50
- }
51
- async deleteTask(taskId) {
52
- const task = await this.datastore.delete(taskId);
53
- return task;
54
- }
55
- registerTaskHandler(input) {
56
- if (this.processors.has(input.kind)) {
57
- throw new Error('Handler for task kind already exists');
58
- }
59
- const processor = (0, processors_1.createProcessor)({
60
- kind: input.kind,
61
- datastore: this.datastore,
62
- handler: input.handler,
63
- backoffStrategyOptions: input.backoffStrategyOptions,
64
- configuration: input.processorConfiguration,
65
- });
66
- this.processors.set(input.kind, processor);
67
- return processor;
68
- }
69
- }
70
- exports.Chrono = Chrono;
71
- //# sourceMappingURL=chrono.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chrono.js","sourceRoot":"","sources":["../src/chrono.ts"],"names":[],"mappings":";;;AAAA,6CAA2C;AAI3C,qCAA8D;AAC9D,6CAA+D;AAG/D,yDAA2D;AAsB3D;;;;;;;;;;GAUG;AAEH,MAAa,MAA8D,SAAQ,0BAA6B;IAC7F,SAAS,CAA2C;IACpD,UAAU,GAAsE,IAAI,GAAG,EAAE,CAAC;IAElG,aAAa,GAAG,MAAM,CAAC;IAEhC,YAAY,SAAmD;QAC7D,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAEM,KAAK,CAAC,KAAK;QAChB,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;YACjD,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,qBAAY,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;IAC7D,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QAE/F,IAAI,CAAC;YACH,MAAM,IAAA,kCAAkB,EAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,qBAAY,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,YAAY,CACvB,KAA2E;QAE3E,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;YACzC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;SACzC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,UAAU,CACrB,MAAc;QAEd,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAW,MAAM,CAAC,CAAC;QAE3D,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,mBAAmB,CACxB,KAAgE;QAEhE,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,SAAS,GAAG,IAAA,4BAAe,EAAC;YAChC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;YACpD,aAAa,EAAE,KAAK,CAAC,sBAAsB;SAC5C,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAE3C,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAtED,wBAsEC"}
@@ -1,63 +0,0 @@
1
- import type { TaskMappingBase } from './chrono';
2
- export declare const TaskStatus: {
3
- readonly PENDING: "PENDING";
4
- readonly CLAIMED: "CLAIMED";
5
- readonly COMPLETED: "COMPLETED";
6
- readonly FAILED: "FAILED";
7
- };
8
- export type TaskStatus = (typeof TaskStatus)[keyof typeof TaskStatus];
9
- export type Task<TaskKind, TaskData> = {
10
- /** A unique identifier for the task */
11
- id: string;
12
- /** A human-readable name or type for the task */
13
- kind: TaskKind;
14
- /** The current status of the task */
15
- status: TaskStatus;
16
- /** The payload or data associated with the task */
17
- data: TaskData;
18
- /** The priority level of the task (lower numbers can indicate higher priority) */
19
- priority?: number;
20
- /** A key used for idempotency to prevent duplicate processing */
21
- idempotencyKey?: string;
22
- /** The original scheduled date when the task was first intended to run */
23
- originalScheduleDate: Date;
24
- /** The current scheduled execution date, which may change if rescheduled */
25
- scheduledAt: Date;
26
- /** The date the task is mark 'claimed */
27
- claimedAt?: Date;
28
- /** The date the task is mark 'completed' */
29
- completedAt?: Date;
30
- /** The date when the task was last executed (if any) */
31
- lastExecutedAt?: Date;
32
- /** A counter to track the number of times the task has been retried */
33
- retryCount: number;
34
- };
35
- export type ScheduleInput<TaskKind, TaskData, DatastoreOptions> = {
36
- when: Date;
37
- kind: TaskKind;
38
- data: TaskData;
39
- priority?: number;
40
- idempotencyKey?: string;
41
- datastoreOptions?: DatastoreOptions;
42
- };
43
- export type ClaimTaskInput<TaskKind> = {
44
- kind: TaskKind;
45
- claimStaleTimeoutMs: number;
46
- };
47
- export type DeleteByIdempotencyKeyInput<TaskKind> = {
48
- kind: TaskKind;
49
- idempotencyKey: string;
50
- };
51
- export type DeleteOptions = {
52
- force?: boolean;
53
- };
54
- export type DeleteInput<TaskKind> = DeleteByIdempotencyKeyInput<TaskKind> | string;
55
- export interface Datastore<TaskMapping extends TaskMappingBase, DatastoreOptions> {
56
- schedule<TaskKind extends keyof TaskMapping>(input: ScheduleInput<TaskKind, TaskMapping[TaskKind], DatastoreOptions>): Promise<Task<TaskKind, TaskMapping[TaskKind]>>;
57
- delete<TaskKind extends keyof TaskMapping>(taskId: string, options?: DeleteOptions): Promise<Task<TaskKind, TaskMapping[TaskKind]> | undefined>;
58
- delete<TaskKind extends keyof TaskMapping>(key: DeleteByIdempotencyKeyInput<TaskKind>, options?: DeleteOptions): Promise<Task<TaskKind, TaskMapping[TaskKind]> | undefined>;
59
- claim<TaskKind extends Extract<keyof TaskMapping, string>>(input: ClaimTaskInput<TaskKind>): Promise<Task<TaskKind, TaskMapping[TaskKind]> | undefined>;
60
- retry<TaskKind extends keyof TaskMapping>(taskId: string, retryAt: Date): Promise<Task<TaskKind, TaskMapping[TaskKind]>>;
61
- complete<TaskKind extends keyof TaskMapping>(taskId: string): Promise<Task<TaskKind, TaskMapping[TaskKind]>>;
62
- fail<TaskKind extends keyof TaskMapping>(taskId: string): Promise<Task<TaskKind, TaskMapping[TaskKind]>>;
63
- }
@@ -1,10 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TaskStatus = void 0;
4
- exports.TaskStatus = {
5
- PENDING: 'PENDING',
6
- CLAIMED: 'CLAIMED',
7
- COMPLETED: 'COMPLETED',
8
- FAILED: 'FAILED',
9
- };
10
- //# sourceMappingURL=datastore.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"datastore.js","sourceRoot":"","sources":["../src/datastore.ts"],"names":[],"mappings":";;;AAEa,QAAA,UAAU,GAAG;IACxB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,QAAQ;CACR,CAAC"}
package/build/events.d.ts DELETED
@@ -1,16 +0,0 @@
1
- export declare const ChronoEvents: {
2
- /** Chrono instance has started processors and begun polling tasks */
3
- readonly STARTED: "started";
4
- /** Chrono instance has failed to gracefully stop so shutdown has been aborted */
5
- readonly STOP_ABORTED: "stopAborted";
6
- };
7
- export type ChronoEvents = (typeof ChronoEvents)[keyof typeof ChronoEvents];
8
- export type ChronoEventsMap = {
9
- [ChronoEvents.STARTED]: [{
10
- startedAt: Date;
11
- }];
12
- [ChronoEvents.STOP_ABORTED]: [{
13
- timestamp: Date;
14
- error: unknown;
15
- }];
16
- };
package/build/events.js DELETED
@@ -1,10 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ChronoEvents = void 0;
4
- exports.ChronoEvents = {
5
- /** Chrono instance has started processors and begun polling tasks */
6
- STARTED: 'started',
7
- /** Chrono instance has failed to gracefully stop so shutdown has been aborted */
8
- STOP_ABORTED: 'stopAborted',
9
- };
10
- //# sourceMappingURL=events.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":";;;AAAa,QAAA,YAAY,GAAG;IAC1B,qEAAqE;IACrE,OAAO,EAAE,SAAS;IAClB,iFAAiF;IACjF,YAAY,EAAE,aAAa;CACnB,CAAC"}
@@ -1,31 +0,0 @@
1
- import type { Datastore, Task } from 'datastore';
2
- import type { TaskMappingBase } from '..';
3
- import { type BackoffStrategyOptions } from '../backoff-strategy';
4
- import type { Processor } from './processor';
5
- /**
6
- * Configuration for the processor.
7
- */
8
- export type ProcessorConfiguration = {
9
- /** The maximum number of concurrent tasks that the processor will use when processing. @default 1 */
10
- maxConcurrency?: number;
11
- /** The interval at which the processor will wait before next poll when the previous poll returned a task @default 50ms */
12
- claimIntervalMs?: number;
13
- /** The interval at which the processor will wait before next poll when no tasks are available for processing @default 5000ms */
14
- idleIntervalMs?: number;
15
- /** The maximum time a task can be claimed for processing before it will be considered stale and claimed again @default 10000ms */
16
- claimStaleTimeoutMs?: number;
17
- /** The maximum time a task handler can take to complete before it will be considered timed out @default 5000ms */
18
- taskHandlerTimeoutMs?: number;
19
- /** The maximum number of retries for a task handler, before task is marked as failed. @default 5 */
20
- taskHandlerMaxRetries?: number;
21
- /** The interval at which the processor will wait before next poll when an unexpected error occurs @default 20000ms */
22
- processLoopRetryIntervalMs?: number;
23
- };
24
- export type CreateProcessorInput<TaskKind extends keyof TaskMapping, TaskMapping extends TaskMappingBase, DatastoreOptions> = {
25
- kind: TaskKind;
26
- datastore: Datastore<TaskMapping, DatastoreOptions>;
27
- handler: (task: Task<TaskKind, TaskMapping[TaskKind]>) => Promise<void>;
28
- configuration?: ProcessorConfiguration;
29
- backoffStrategyOptions?: BackoffStrategyOptions;
30
- };
31
- export declare function createProcessor<TaskKind extends Extract<keyof TaskMapping, string>, TaskMapping extends TaskMappingBase, DatastoreOptions>(input: CreateProcessorInput<TaskKind, TaskMapping, DatastoreOptions>): Processor<TaskKind, TaskMapping>;
@@ -1,11 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createProcessor = createProcessor;
4
- const backoff_strategy_1 = require("../backoff-strategy");
5
- const simple_processor_1 = require("./simple-processor");
6
- function createProcessor(input) {
7
- const backoffStrategy = (0, backoff_strategy_1.backoffStrategyFactory)(input.backoffStrategyOptions);
8
- // add more processors here
9
- return new simple_processor_1.SimpleProcessor(input.datastore, input.kind, input.handler, backoffStrategy, input.configuration);
10
- }
11
- //# sourceMappingURL=create-processor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-processor.js","sourceRoot":"","sources":["../../src/processors/create-processor.ts"],"names":[],"mappings":";;AAsCA,0CAcC;AAlDD,0DAA0F;AAE1F,yDAAqD;AAkCrD,SAAgB,eAAe,CAI7B,KAAoE;IACpE,MAAM,eAAe,GAAG,IAAA,yCAAsB,EAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC7E,2BAA2B;IAC3B,OAAO,IAAI,kCAAe,CACxB,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,OAAO,EACb,eAAe,EACf,KAAK,CAAC,aAAa,CACpB,CAAC;AACJ,CAAC"}
@@ -1,50 +0,0 @@
1
- import type { Task, TaskMappingBase } from '..';
2
- export declare const ProcessorEvents: {
3
- /** A task has been claimed by the running processor for handling */
4
- readonly TASK_CLAIMED: "taskClaimed";
5
- /** A task has completed processing and successfully marked as completed */
6
- readonly TASK_COMPLETED: "taskCompleted";
7
- /** A task has failed during processing and being scheduled for retry */
8
- readonly TASK_RETRY_SCHEDULED: "taskRetryScheduled";
9
- /** A task has been marked as FAILED due to process failures exceeding max retries */
10
- readonly TASK_FAILED: "taskFailed";
11
- /** A task has been successfully processed but underlying data store failed to mark task as completed. Duplicate processing expected */
12
- readonly TASK_COMPLETION_FAILURE: "taskCompletionFailure";
13
- /** An unknown and uncaught exception occurred in processor. Processing paused for processLoopRetryIntervalMs before continuing */
14
- readonly UNKNOWN_PROCESSING_ERROR: "unknownProcessingError";
15
- };
16
- export type ProcessorEvents = (typeof ProcessorEvents)[keyof typeof ProcessorEvents];
17
- export type ProcessorEventsMap<TaskKind extends keyof TaskMapping, TaskMapping extends TaskMappingBase> = {
18
- [ProcessorEvents.TASK_CLAIMED]: [{
19
- task: Task<TaskKind, TaskMapping[TaskKind]>;
20
- claimedAt: Date;
21
- }];
22
- [ProcessorEvents.TASK_COMPLETED]: [{
23
- task: Task<TaskKind, TaskMapping[TaskKind]>;
24
- completedAt: Date;
25
- }];
26
- [ProcessorEvents.TASK_RETRY_SCHEDULED]: [
27
- {
28
- task: Task<TaskKind, TaskMapping[TaskKind]>;
29
- error: unknown;
30
- retryScheduledAt: Date;
31
- errorAt: Date;
32
- }
33
- ];
34
- [ProcessorEvents.TASK_FAILED]: [{
35
- task: Task<TaskKind, TaskMapping[TaskKind]>;
36
- error: unknown;
37
- failedAt: Date;
38
- }];
39
- [ProcessorEvents.TASK_COMPLETION_FAILURE]: [
40
- {
41
- task: Task<TaskKind, TaskMapping[TaskKind]>;
42
- error: unknown;
43
- failedAt: Date;
44
- }
45
- ];
46
- [ProcessorEvents.UNKNOWN_PROCESSING_ERROR]: [{
47
- error: unknown;
48
- timestamp: Date;
49
- }];
50
- };
@@ -1,19 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ProcessorEvents = void 0;
4
- exports.ProcessorEvents = {
5
- /** A task has been claimed by the running processor for handling */
6
- TASK_CLAIMED: 'taskClaimed',
7
- /** A task has completed processing and successfully marked as completed */
8
- TASK_COMPLETED: 'taskCompleted',
9
- /** A task has failed during processing and being scheduled for retry */
10
- TASK_RETRY_SCHEDULED: 'taskRetryScheduled',
11
- /** A task has been marked as FAILED due to process failures exceeding max retries */
12
- TASK_FAILED: 'taskFailed',
13
- /** A task has been successfully processed but underlying data store failed to mark task as completed. Duplicate processing expected */
14
- TASK_COMPLETION_FAILURE: 'taskCompletionFailure',
15
- /** An unknown and uncaught exception occurred in processor. Processing paused for processLoopRetryIntervalMs before continuing */
16
- UNKNOWN_PROCESSING_ERROR: 'unknownProcessingError',
17
- };
18
- exports.ProcessorEvents.TASK_CLAIMED;
19
- //# sourceMappingURL=events.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/processors/events.ts"],"names":[],"mappings":";;;AAEa,QAAA,eAAe,GAAG;IAC7B,oEAAoE;IACpE,YAAY,EAAE,aAAa;IAC3B,2EAA2E;IAC3E,cAAc,EAAE,eAAe;IAC/B,wEAAwE;IACxE,oBAAoB,EAAE,oBAAoB;IAC1C,qFAAqF;IACrF,WAAW,EAAE,YAAY;IACzB,uIAAuI;IACvI,uBAAuB,EAAE,uBAAuB;IAChD,kIAAkI;IAClI,wBAAwB,EAAE,wBAAwB;CAC1C,CAAC;AAiBX,uBAAe,CAAC,YAAY,CAAC"}
@@ -1,3 +0,0 @@
1
- export { createProcessor } from './create-processor';
2
- export type { Processor } from './processor';
3
- export { ProcessorEvents, type ProcessorEventsMap } from './events';
@@ -1,8 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ProcessorEvents = exports.createProcessor = void 0;
4
- var create_processor_1 = require("./create-processor");
5
- Object.defineProperty(exports, "createProcessor", { enumerable: true, get: function () { return create_processor_1.createProcessor; } });
6
- var events_1 = require("./events");
7
- Object.defineProperty(exports, "ProcessorEvents", { enumerable: true, get: function () { return events_1.ProcessorEvents; } });
8
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/processors/index.ts"],"names":[],"mappings":";;;AAAA,uDAAqD;AAA5C,mHAAA,eAAe,OAAA;AAExB,mCAAoE;AAA3D,yGAAA,eAAe,OAAA"}
@@ -1,7 +0,0 @@
1
- import type { EventEmitter } from 'node:stream';
2
- import type { TaskMappingBase } from '..';
3
- import type { ProcessorEventsMap } from './events';
4
- export interface Processor<TaskKind extends keyof TaskMapping, TaskMapping extends TaskMappingBase> extends EventEmitter<ProcessorEventsMap<TaskKind, TaskMapping>> {
5
- start(): Promise<void>;
6
- stop(): Promise<void>;
7
- }
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=processor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"processor.js","sourceRoot":"","sources":["../../src/processors/processor.ts"],"names":[],"mappings":""}
@@ -1,63 +0,0 @@
1
- import { EventEmitter } from 'node:stream';
2
- import type { BackoffStrategy } from '../backoff-strategy';
3
- import type { TaskMappingBase } from '../chrono';
4
- import type { Datastore, Task } from '../datastore';
5
- import { type ProcessorEventsMap } from './events';
6
- import type { Processor } from './processor';
7
- type SimpleProcessorConfig = {
8
- maxConcurrency: number;
9
- claimIntervalMs: number;
10
- claimStaleTimeoutMs: number;
11
- idleIntervalMs: number;
12
- taskHandlerTimeoutMs: number;
13
- taskHandlerMaxRetries: number;
14
- processLoopRetryIntervalMs: number;
15
- };
16
- export declare class SimpleProcessor<TaskKind extends Extract<keyof TaskMapping, string>, TaskMapping extends TaskMappingBase, DatastoreOptions> extends EventEmitter<ProcessorEventsMap<TaskKind, TaskMapping>> implements Processor<TaskKind, TaskMapping> {
17
- private datastore;
18
- private taskKind;
19
- private handler;
20
- private backOffStrategy;
21
- private config;
22
- private exitChannels;
23
- private stopRequested;
24
- constructor(datastore: Datastore<TaskMapping, DatastoreOptions>, taskKind: TaskKind, handler: (task: Task<TaskKind, TaskMapping[TaskKind]>) => Promise<void>, backOffStrategy: BackoffStrategy, config?: Partial<SimpleProcessorConfig>);
25
- /**
26
- * Validates that the task handler timeout is less than the claim stale timeout.
27
- * Throws an error if the validation fails.
28
- * This ensures that the task handler has enough time to complete before the task is considered stale.
29
- * This is important to prevent tasks from being claimed again while they are still being processed.
30
- *
31
- * @throws {Error} If the task handler timeout is greater than or equal to the claim stale timeout.
32
- */
33
- private validatedHandlerTimeout;
34
- /**
35
- * Starts multiple concurrent process loops that claim and process tasks.
36
- * Max concurrent processes is defined by the `maxConcurrency` property set in the constructor.
37
- */
38
- start(): Promise<void>;
39
- /**
40
- * Stops the processor by signaling all process loops to exit,
41
- * then waits for all process loops to finish before resolving.
42
- */
43
- stop(): Promise<void>;
44
- /**
45
- * The main loop that processes tasks.
46
- *
47
- * @param exitChannel The channel to signal when the loop exits.
48
- */
49
- private runProcessLoop;
50
- /**
51
- * Handles a task by calling the handler and marking it as complete or failed.
52
- *
53
- * Emits:
54
- * - `task.completed` when the task is successfully completed.
55
- * - `task.failed` when the task fails.
56
- * - `task.complete.failed` when the task fails to mark as completed.
57
- *
58
- * @param task The task to handle.
59
- */
60
- private handleTask;
61
- private handleTaskError;
62
- }
63
- export {};
@@ -1,161 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SimpleProcessor = void 0;
4
- const node_stream_1 = require("node:stream");
5
- const promises_1 = require("node:timers/promises");
6
- const promise_utils_1 = require("../utils/promise-utils");
7
- const events_1 = require("./events");
8
- const DEFAULT_CONFIG = {
9
- maxConcurrency: 1,
10
- claimIntervalMs: 50,
11
- idleIntervalMs: 5_000,
12
- claimStaleTimeoutMs: 10_000,
13
- taskHandlerTimeoutMs: 5_000,
14
- taskHandlerMaxRetries: 5,
15
- processLoopRetryIntervalMs: 20_000,
16
- };
17
- const InternalProcessorEvents = { PROCESSOR_LOOP_EXIT: 'processorLoopExit' };
18
- class SimpleProcessor extends node_stream_1.EventEmitter {
19
- datastore;
20
- taskKind;
21
- handler;
22
- backOffStrategy;
23
- config;
24
- exitChannels = [];
25
- stopRequested = false;
26
- constructor(datastore, taskKind, handler, backOffStrategy, config) {
27
- super();
28
- this.datastore = datastore;
29
- this.taskKind = taskKind;
30
- this.handler = handler;
31
- this.backOffStrategy = backOffStrategy;
32
- this.config = {
33
- ...DEFAULT_CONFIG,
34
- ...config,
35
- };
36
- this.validatedHandlerTimeout();
37
- }
38
- /**
39
- * Validates that the task handler timeout is less than the claim stale timeout.
40
- * Throws an error if the validation fails.
41
- * This ensures that the task handler has enough time to complete before the task is considered stale.
42
- * This is important to prevent tasks from being claimed again while they are still being processed.
43
- *
44
- * @throws {Error} If the task handler timeout is greater than or equal to the claim stale timeout.
45
- */
46
- validatedHandlerTimeout() {
47
- if (this.config.taskHandlerTimeoutMs >= this.config.claimStaleTimeoutMs) {
48
- throw new Error(`Task handler timeout (${this.config.taskHandlerTimeoutMs}ms) must be less than the claim stale timeout (${this.config.claimStaleTimeoutMs}ms)`);
49
- }
50
- }
51
- /**
52
- * Starts multiple concurrent process loops that claim and process tasks.
53
- * Max concurrent processes is defined by the `maxConcurrency` property set in the constructor.
54
- */
55
- async start() {
56
- if (this.stopRequested || this.exitChannels.length > 0) {
57
- return;
58
- }
59
- for (let i = 0; i < this.config.maxConcurrency; i++) {
60
- const exitChannel = new node_stream_1.EventEmitter();
61
- this.exitChannels.push(exitChannel);
62
- this.runProcessLoop(exitChannel);
63
- }
64
- }
65
- /**
66
- * Stops the processor by signaling all process loops to exit,
67
- * then waits for all process loops to finish before resolving.
68
- */
69
- async stop() {
70
- const exitPromises = this.exitChannels.map((channel) => new Promise((resolve) => channel.once(InternalProcessorEvents.PROCESSOR_LOOP_EXIT, () => resolve(null))));
71
- this.stopRequested = true;
72
- await Promise.all(exitPromises);
73
- }
74
- /**
75
- * The main loop that processes tasks.
76
- *
77
- * @param exitChannel The channel to signal when the loop exits.
78
- */
79
- async runProcessLoop(exitChannel) {
80
- while (!this.stopRequested) {
81
- try {
82
- const task = await this.datastore.claim({
83
- kind: this.taskKind,
84
- claimStaleTimeoutMs: this.config.claimStaleTimeoutMs,
85
- });
86
- // If no tasks are available, wait before trying again
87
- if (!task) {
88
- await (0, promises_1.setTimeout)(this.config.idleIntervalMs);
89
- continue;
90
- }
91
- this.emit(events_1.ProcessorEvents.TASK_CLAIMED, { task, claimedAt: task.claimedAt || new Date() });
92
- // Process the task using the handler
93
- await this.handleTask(task);
94
- // Wait a bit before claiming the next task
95
- await (0, promises_1.setTimeout)(this.config.claimIntervalMs);
96
- }
97
- catch (error) {
98
- this.emit(events_1.ProcessorEvents.UNKNOWN_PROCESSING_ERROR, { error, timestamp: new Date() });
99
- await (0, promises_1.setTimeout)(this.config.processLoopRetryIntervalMs);
100
- }
101
- }
102
- exitChannel.emit(InternalProcessorEvents.PROCESSOR_LOOP_EXIT);
103
- }
104
- /**
105
- * Handles a task by calling the handler and marking it as complete or failed.
106
- *
107
- * Emits:
108
- * - `task.completed` when the task is successfully completed.
109
- * - `task.failed` when the task fails.
110
- * - `task.complete.failed` when the task fails to mark as completed.
111
- *
112
- * @param task The task to handle.
113
- */
114
- async handleTask(task) {
115
- try {
116
- await (0, promise_utils_1.promiseWithTimeout)(this.handler(task), this.config.taskHandlerTimeoutMs);
117
- }
118
- catch (error) {
119
- await this.handleTaskError(task, error);
120
- return;
121
- }
122
- try {
123
- const completedTask = await this.datastore.complete(task.id);
124
- this.emit(events_1.ProcessorEvents.TASK_COMPLETED, {
125
- task: completedTask,
126
- completedAt: completedTask.completedAt || new Date(),
127
- });
128
- }
129
- catch (error) {
130
- this.emit(events_1.ProcessorEvents.TASK_COMPLETION_FAILURE, {
131
- error: error,
132
- failedAt: new Date(),
133
- task,
134
- });
135
- }
136
- }
137
- async handleTaskError(task, error) {
138
- const failedAt = new Date();
139
- if (task.retryCount >= this.config.taskHandlerMaxRetries) {
140
- // Mark the task as failed
141
- await this.datastore.fail(task.id);
142
- this.emit(events_1.ProcessorEvents.TASK_FAILED, {
143
- task,
144
- error,
145
- failedAt,
146
- });
147
- return;
148
- }
149
- const delay = this.backOffStrategy({ retryAttempt: task.retryCount });
150
- const retryAt = new Date(Date.now() + delay);
151
- await this.datastore.retry(task.id, retryAt);
152
- this.emit(events_1.ProcessorEvents.TASK_RETRY_SCHEDULED, {
153
- task,
154
- error,
155
- errorAt: failedAt,
156
- retryScheduledAt: retryAt,
157
- });
158
- }
159
- }
160
- exports.SimpleProcessor = SimpleProcessor;
161
- //# sourceMappingURL=simple-processor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"simple-processor.js","sourceRoot":"","sources":["../../src/processors/simple-processor.ts"],"names":[],"mappings":";;;AAAA,6CAA2C;AAC3C,mDAAkD;AAKlD,0DAA4D;AAC5D,qCAAoE;AAGpE,MAAM,cAAc,GAA0B;IAC5C,cAAc,EAAE,CAAC;IACjB,eAAe,EAAE,EAAE;IACnB,cAAc,EAAE,KAAK;IACrB,mBAAmB,EAAE,MAAM;IAC3B,oBAAoB,EAAE,KAAK;IAC3B,qBAAqB,EAAE,CAAC;IACxB,0BAA0B,EAAE,MAAM;CACnC,CAAC;AAYF,MAAM,uBAAuB,GAAG,EAAE,mBAAmB,EAAE,mBAAmB,EAAW,CAAC;AAOtF,MAAa,eAKX,SAAQ,0BAAuD;IASrD;IACA;IACA;IACA;IATF,MAAM,CAAwB;IAE9B,YAAY,GAA+C,EAAE,CAAC;IAC9D,aAAa,GAAG,KAAK,CAAC;IAE9B,YACU,SAAmD,EACnD,QAAkB,EAClB,OAAuE,EACvE,eAAgC,EACxC,MAAuC;QAEvC,KAAK,EAAE,CAAC;QANA,cAAS,GAAT,SAAS,CAA0C;QACnD,aAAQ,GAAR,QAAQ,CAAU;QAClB,YAAO,GAAP,OAAO,CAAgE;QACvE,oBAAe,GAAf,eAAe,CAAiB;QAKxC,IAAI,CAAC,MAAM,GAAG;YACZ,GAAG,cAAc;YACjB,GAAG,MAAM;SACV,CAAC;QAEF,IAAI,CAAC,uBAAuB,EAAE,CAAC;IACjC,CAAC;IAED;;;;;;;OAOG;IACK,uBAAuB;QAC7B,IAAI,IAAI,CAAC,MAAM,CAAC,oBAAoB,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;YACxE,MAAM,IAAI,KAAK,CACb,yBAAyB,IAAI,CAAC,MAAM,CAAC,oBAAoB,kDAAkD,IAAI,CAAC,MAAM,CAAC,mBAAmB,KAAK,CAChJ,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,OAAO;QACT,CAAC;QAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC;YACpD,MAAM,WAAW,GAAG,IAAI,0BAAY,EAA8B,CAAC;YAEnE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACpC,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CACxC,CAAC,OAAO,EAAE,EAAE,CACV,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAC3G,CAAC;QAEF,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAE1B,MAAM,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,cAAc,CAAC,WAAqD;QAChF,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;oBACtC,IAAI,EAAE,IAAI,CAAC,QAAQ;oBACnB,mBAAmB,EAAE,IAAI,CAAC,MAAM,CAAC,mBAAmB;iBACrD,CAAC,CAAC;gBAEH,sDAAsD;gBACtD,IAAI,CAAC,IAAI,EAAE,CAAC;oBACV,MAAM,IAAA,qBAAU,EAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;oBAE7C,SAAS;gBACX,CAAC;gBAED,IAAI,CAAC,IAAI,CAAC,wBAAe,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;gBAE3F,qCAAqC;gBACrC,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;gBAE5B,2CAA2C;gBAC3C,MAAM,IAAA,qBAAU,EAAC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAChD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,IAAI,CAAC,wBAAe,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;gBAEtF,MAAM,IAAA,qBAAU,EAAC,IAAI,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC;QAED,WAAW,CAAC,IAAI,CAAC,uBAAuB,CAAC,mBAAmB,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;;;OASG;IACK,KAAK,CAAC,UAAU,CAAC,IAA2C;QAClE,IAAI,CAAC;YACH,MAAM,IAAA,kCAAkB,EAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACjF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,KAAc,CAAC,CAAC;YAEjD,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAW,IAAI,CAAC,EAAE,CAAC,CAAC;YAEvE,IAAI,CAAC,IAAI,CAAC,wBAAe,CAAC,cAAc,EAAE;gBACxC,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE,aAAa,CAAC,WAAW,IAAI,IAAI,IAAI,EAAE;aACrD,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,wBAAe,CAAC,uBAAuB,EAAE;gBACjD,KAAK,EAAE,KAAK;gBACZ,QAAQ,EAAE,IAAI,IAAI,EAAE;gBACpB,IAAI;aACL,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,IAA2C,EAAE,KAAY;QACrF,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC;YACzD,0BAA0B;YAC1B,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,wBAAe,CAAC,WAAW,EAAE;gBACrC,IAAI;gBACJ,KAAK;gBACL,QAAQ;aACT,CAAC,CAAC;YAEH,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;QAE7C,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI,CAAC,wBAAe,CAAC,oBAAoB,EAAE;YAC9C,IAAI;YACJ,KAAK;YACL,OAAO,EAAE,QAAQ;YACjB,gBAAgB,EAAE,OAAO;SAC1B,CAAC,CAAC;IACL,CAAC;CACF;AA/KD,0CA+KC"}
@@ -1,9 +0,0 @@
1
- export interface Task<T> {
2
- run(): Promise<T>;
3
- }
4
- export declare class Scheduler<T> {
5
- #private;
6
- constructor();
7
- schedule(task: Task<T>): Promise<boolean>;
8
- run(): Promise<boolean>;
9
- }
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Scheduler = void 0;
4
- class Scheduler {
5
- #tasks = [];
6
- constructor() {
7
- this.#tasks = [];
8
- }
9
- async schedule(task) {
10
- this.#tasks.push(task);
11
- return true;
12
- }
13
- async run() {
14
- for (const task of this.#tasks) {
15
- task.run();
16
- }
17
- return true;
18
- }
19
- }
20
- exports.Scheduler = Scheduler;
21
- //# sourceMappingURL=scheduler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":";;;AAIA,MAAa,SAAS;IACpB,MAAM,GAAc,EAAE,CAAC;IAEvB;QACE,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACnB,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,IAAa;QACjC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEvB,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,GAAG;QACd,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AApBD,8BAoBC"}
package/build/task.d.ts DELETED
@@ -1,33 +0,0 @@
1
- export declare const TaskStatus: {
2
- readonly PENDING: "PENDING";
3
- readonly CLAIMED: "CLAIMED";
4
- readonly COMPLETED: "COMPLETED";
5
- readonly FAILED: "FAILED";
6
- };
7
- export type TaskStatus = (typeof TaskStatus)[keyof typeof TaskStatus];
8
- export type Task<TaskKind, TaskData> = {
9
- /** A unique identifier for the task */
10
- id: string;
11
- /** A human-readable name or type for the task */
12
- kind: TaskKind;
13
- /** The current status of the task */
14
- status: TaskStatus;
15
- /** The payload or data associated with the task */
16
- data: TaskData;
17
- /** The priority level of the task (lower numbers can indicate higher priority) */
18
- priority?: number;
19
- /** A key used for idempotency to prevent duplicate processing */
20
- idempotencyKey?: string;
21
- /** The original scheduled date when the task was first intended to run */
22
- originalScheduleDate: Date;
23
- /** The current scheduled execution date, which may change if rescheduled */
24
- scheduledAt: Date;
25
- /** The date the task is mark 'claimed */
26
- claimedAt?: Date;
27
- /** The date the task is mark 'completed' */
28
- completedAt?: Date;
29
- /** The date when the task was last executed (if any) */
30
- lastExecutedAt?: Date;
31
- /** A counter to track the number of times the task has been retried */
32
- retryCount: number;
33
- };