fyflow-scheduler 0.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.
Files changed (32) hide show
  1. package/AGENTS.md +577 -0
  2. package/LICENSE +21 -0
  3. package/README.md +415 -0
  4. package/dist/browser/index.js +2378 -0
  5. package/dist/node/index.js +2380 -0
  6. package/dist/types/core/FyflowScheduler.d.ts +279 -0
  7. package/dist/types/core/FyflowScheduler.d.ts.map +1 -0
  8. package/dist/types/core/inlineWrapper.d.ts +45 -0
  9. package/dist/types/core/inlineWrapper.d.ts.map +1 -0
  10. package/dist/types/core/threadWrapper.d.ts +59 -0
  11. package/dist/types/core/threadWrapper.d.ts.map +1 -0
  12. package/dist/types/core/workerInterface.d.ts +166 -0
  13. package/dist/types/core/workerInterface.d.ts.map +1 -0
  14. package/dist/types/core/workerManager.d.ts +141 -0
  15. package/dist/types/core/workerManager.d.ts.map +1 -0
  16. package/dist/types/core/workerWrapper.d.ts +2 -0
  17. package/dist/types/core/workerWrapper.d.ts.map +1 -0
  18. package/dist/types/core/workerWrapperUrl.bundled.d.ts +2 -0
  19. package/dist/types/core/workerWrapperUrl.bundled.d.ts.map +1 -0
  20. package/dist/types/core/workerWrapperUrl.d.ts +2 -0
  21. package/dist/types/core/workerWrapperUrl.d.ts.map +1 -0
  22. package/dist/types/groups/concurrentLimitGroup.d.ts +33 -0
  23. package/dist/types/groups/concurrentLimitGroup.d.ts.map +1 -0
  24. package/dist/types/groups/keyedRateLimitGroup.d.ts +98 -0
  25. package/dist/types/groups/keyedRateLimitGroup.d.ts.map +1 -0
  26. package/dist/types/groups/rateLimitGroup.d.ts +79 -0
  27. package/dist/types/groups/rateLimitGroup.d.ts.map +1 -0
  28. package/dist/types/groups/resourceGroup.d.ts +41 -0
  29. package/dist/types/groups/resourceGroup.d.ts.map +1 -0
  30. package/dist/types/index.d.ts +15 -0
  31. package/dist/types/index.d.ts.map +1 -0
  32. package/package.json +83 -0
@@ -0,0 +1,279 @@
1
+ /**
2
+ * A unit of work handed to a worker pool.
3
+ *
4
+ * Tasks are independent - there is no dependency graph. A task runs as soon as
5
+ * its worker pool has capacity and every resource group it belongs to has a
6
+ * free slot.
7
+ *
8
+ * ```typescript
9
+ * const task = new FyflowTask({
10
+ * id: 'resize-image-42',
11
+ * workerType: 'ImageWorker', // key in the scheduler's workerPools
12
+ * payload: { path: '/tmp/42.png' }
13
+ * });
14
+ * const result = await scheduler.addTask(task, { createPromise: true });
15
+ * ```
16
+ */
17
+ export declare class FyflowTask {
18
+ id: string;
19
+ workerType: string;
20
+ payload: any;
21
+ optional: boolean;
22
+ retryPolicy?: {
23
+ maxRetries: number;
24
+ backoffMs: number;
25
+ };
26
+ /** Retry attempts used so far, counted against `retryPolicy.maxRetries`. */
27
+ attempts: number;
28
+ /**
29
+ * `pending` -> `running` -> `done` | `failed`.
30
+ *
31
+ * A non-optional task that fails with no retries left ends in `user_action`,
32
+ * signalling that something outside the scheduler has to intervene.
33
+ */
34
+ state: string;
35
+ result?: any;
36
+ error?: string;
37
+ resolve?: Function;
38
+ reject?: Function;
39
+ workerGroups?: string[];
40
+ handleRejection: boolean;
41
+ startTime?: number;
42
+ endTime?: number;
43
+ /**
44
+ * Worker-measured execution time in ms (high resolution), set on completion.
45
+ * Unlike `endTime - startTime` this excludes time spent waiting for a worker
46
+ * slot. Cleared when a task is requeued or retried.
47
+ */
48
+ executionTime?: number;
49
+ /**
50
+ * Bucket this task belongs to for keyed resource groups. Read by the default
51
+ * `keyFrom` of {@link KeyedRateLimitGroup}; a group given its own `keyFrom`
52
+ * can derive the key from the payload instead.
53
+ */
54
+ limitKey?: string;
55
+ _resourcesPreAllocated?: boolean;
56
+ /**
57
+ * Keys resolved at dispatch, per keyed group id. Held so release uses the
58
+ * same bucket acquisition used, even if the payload changed meanwhile.
59
+ */
60
+ _resourceKeys?: Record<string, string>;
61
+ /**
62
+ * Set while this attempt is being settled, so the same outcome arriving from
63
+ * both the pool's `task.failed` event and the task promise settles once.
64
+ * Cleared on every dispatch, so each attempt gets its own settle.
65
+ */
66
+ _settling?: boolean;
67
+ _scheduler?: FyflowScheduler;
68
+ /**
69
+ * @param config.id Unique task id. Reusing an id overwrites the earlier entry.
70
+ * @param config.workerType Key into the scheduler's `workerPools`. An unknown
71
+ * value makes `addTask` throw.
72
+ * @param config.payload Passed verbatim to the worker's `run()`.
73
+ * @param config.optional Default `false`. An optional task that fails
74
+ * resolves `null` instead of rejecting.
75
+ * @param config.retryPolicy `{ maxRetries, backoffMs }`. Omitted means no retries.
76
+ * @param config.workerGroups Resource groups for this task, *in addition* to
77
+ * the groups its WorkerManager declares.
78
+ * @param config.handleRejection Default `true`. Attaches a silent catch so a
79
+ * fire-and-forget failure does not surface as an unhandled rejection;
80
+ * `task.failed` is still emitted.
81
+ * @param config.limitKey Bucket for keyed resource groups, e.g. the endpoint
82
+ * or tenant this task belongs to. Required when the task belongs to a
83
+ * keyed group that has no custom `keyFrom`.
84
+ */
85
+ constructor({ id, workerType, payload, optional, retryPolicy, workerGroups, handleRejection, limitKey }: any);
86
+ /**
87
+ * Promise for this task alone, resolving with its result and rejecting if it
88
+ * fails. Prefer `addTask(task, { createPromise: true })`, which wires this up
89
+ * for you. Use `onCompleteDescendants()` to also wait for spawned tasks.
90
+ */
91
+ onCompletePromise(): Promise<any>;
92
+ /**
93
+ * Wait for this task AND every task spawned from it (children, grandchildren, ...)
94
+ * to reach a terminal state.
95
+ *
96
+ * Descendants come from runtime spawning via `context.spawnTask()` - this is
97
+ * lineage, not a scheduling dependency, and does not affect dispatch order.
98
+ *
99
+ * Resolves with this task's result once the whole workflow has settled. A failed
100
+ * descendant does not reject - descendant failures surface via `task.failed`
101
+ * events - but this task failing rejects, matching `onCompletePromise()`.
102
+ *
103
+ * Must be called after the task has been added to a scheduler.
104
+ */
105
+ onCompleteDescendants(): Promise<any>;
106
+ }
107
+ export interface FyflowSchedulerOptions {
108
+ periodicRetryIntervalMs?: number;
109
+ /**
110
+ * Maximum number of terminal (done/failed/user_action) tasks to keep in
111
+ * `scheduler.tasks`. Once exceeded, the oldest-completed tasks are evicted
112
+ * along with their payloads, results and spawn lineage.
113
+ *
114
+ * Default: undefined - keep everything, which is what most workloads want
115
+ * since task counts are bounded and completed tasks stay inspectable. Set
116
+ * this for long-lived schedulers, where retention is otherwise unbounded.
117
+ *
118
+ * `stats` counts every task regardless, and in-flight tasks are never
119
+ * evicted.
120
+ */
121
+ maxCompletedTasks?: number;
122
+ }
123
+ export interface AddTaskOptions {
124
+ createPromise?: boolean;
125
+ }
126
+ /**
127
+ * Runs tasks in parallel across worker pools, subject to resource groups.
128
+ *
129
+ * ```typescript
130
+ * const scheduler = new FyflowScheduler(
131
+ * { ImageWorker: new WorkerManager(workerUrl, { maxThreads: 4, groups: ['cpu'] }) },
132
+ * { cpu: new ConcurrentLimitGroup(8, 'cpu') }
133
+ * );
134
+ * scheduler.addTask(task); // fire-and-forget
135
+ * await scheduler.shutdown(); // always shut down when finished
136
+ * ```
137
+ *
138
+ * Emits: `task.running`, `task.completed`, `task.failed`, `task.progress`,
139
+ * `task.user_action`, `task.spawn_request`, `task.spawn_failed` and
140
+ * `scheduler.completed`.
141
+ */
142
+ export declare class FyflowScheduler extends EventTarget {
143
+ tasks: Map<string, FyflowTask>;
144
+ readyQueuesByWorker: Map<string, FyflowTask[]>;
145
+ blockedQueues: Map<string, FyflowTask[]>;
146
+ workerPools: any;
147
+ groups: Record<string, any>;
148
+ stats: {
149
+ queued: number;
150
+ running: number;
151
+ done: number;
152
+ failed: number;
153
+ };
154
+ private retryTimer;
155
+ private descendantTrackers;
156
+ private nextTrackerId;
157
+ private spawnedChildren;
158
+ private completedTaskIds;
159
+ private options;
160
+ private allListeners;
161
+ constructor(workerPools: any, groups?: Record<string, any>, options?: FyflowSchedulerOptions);
162
+ /** Every resource group a task must acquire: its own plus its pool's. */
163
+ private _groupsForTask;
164
+ /**
165
+ * Blocked queues are per group, and per (group, key) for keyed groups, so a
166
+ * saturated key never stalls tasks belonging to a different one.
167
+ */
168
+ private _blockedQueueId;
169
+ /**
170
+ * Resolve the bucket for every keyed group this task belongs to.
171
+ *
172
+ * @throws if a keyed group cannot derive a key. A keyless task would
173
+ * otherwise silently share a bucket with every other keyless task, or skip
174
+ * the limit entirely - both discovered only once something is throttled.
175
+ */
176
+ private _resolveResourceKeys;
177
+ private _hasBlockedTasks;
178
+ _checkCompletion(): void;
179
+ /**
180
+ * Queue a task and start dispatching.
181
+ *
182
+ * Fire-and-forget by default: returns `undefined` unless
183
+ * `{ createPromise: true }` is passed, in which case it returns a promise
184
+ * that resolves with the task's result or rejects if it fails.
185
+ *
186
+ * @throws if `task.workerType` is not a key in the scheduler's `workerPools`.
187
+ */
188
+ addTask(task: FyflowTask, options?: AddTaskOptions): Promise<any> | void;
189
+ /**
190
+ * Queue many tasks with a single dispatch pass - use this for bulk additions
191
+ * (>1000 tasks) instead of calling `addTask` in a loop, which would run the
192
+ * dispatch loop once per task.
193
+ *
194
+ * Like `addTask`, returns nothing unless `{ createPromise: true }` is passed;
195
+ * with it, returns one promise per task in the same order:
196
+ *
197
+ * ```typescript
198
+ * const results = await Promise.all(
199
+ * scheduler.addTasks(tasks, { createPromise: true }) as Promise<any>[]
200
+ * );
201
+ * ```
202
+ *
203
+ * @throws if any task's `workerType` is not a key in the scheduler's
204
+ * `workerPools`. The batch is validated up front, so a rejected call
205
+ * queues nothing at all.
206
+ */
207
+ addTasks(tasks: FyflowTask[], options?: AddTaskOptions): Promise<any>[] | void;
208
+ _dispatchLoop(): void;
209
+ _checkAndBlockResources(task: FyflowTask, pool: any): true | 'blocked' | 'blocked-keyed';
210
+ _canDispatchTask(task: FyflowTask, pool: any): boolean | 'blocked' | 'blocked-keyed';
211
+ _dispatchTask(task: FyflowTask, pool: any): void;
212
+ _releaseResourcesForTask(task: FyflowTask, pool: any): void;
213
+ /**
214
+ * The one place a task settles.
215
+ *
216
+ * An outcome can reach the scheduler twice - as the pool's `task.failed`
217
+ * event and as the settling of the pool's task promise - and each of those
218
+ * is the ONLY path in some situation, so neither can be dropped:
219
+ *
220
+ * - an ordinary task throw reaches both
221
+ * - a worker that dies with `requeueFailedTasks: false` reaches only the event
222
+ * - a worker that cannot be constructed reaches only the promise
223
+ *
224
+ * They used to be two near-duplicate implementations, so a single failure
225
+ * emitted `task.failed` twice, counted `stats.failed` twice, raced the
226
+ * terminal state between `user_action` and `failed`, and - because only the
227
+ * promise path released resources - leaked a resource group slot whenever
228
+ * only the event path ran.
229
+ */
230
+ private _settleTask;
231
+ _onTaskComplete(task: FyflowTask, result: any, pool: any): void;
232
+ _onTaskFailed(task: FyflowTask, error: any, pool: any): void;
233
+ _retryBlockedTasks(): void;
234
+ /** Keys that currently have tasks blocked on this group. */
235
+ private _blockedKeysFor;
236
+ _retryBlockedTasksForGroup(groupId: string, key?: string): void;
237
+ _schedulePeriodicRetry(): void;
238
+ _clearPeriodicRetry(): void;
239
+ private _addInternalListener;
240
+ private _trackListener;
241
+ private _removeAllListeners;
242
+ _setupGroupEventListeners(): void;
243
+ _setupWorkerPoolListeners(): void;
244
+ private static readonly TERMINAL_STATES;
245
+ private _isTerminal;
246
+ private _recordSpawn;
247
+ _trackDescendants(task: FyflowTask, resolve: Function, reject: Function): void;
248
+ private _collectPendingDescendants;
249
+ private _recordTerminalTask;
250
+ private _settleDescendantTrackers;
251
+ private _settleTracker;
252
+ private _addSpawnedTaskToTrackers;
253
+ /**
254
+ * Get current metrics for all resource groups
255
+ *
256
+ * Returns real-time utilization and availability for monitoring
257
+ *
258
+ * @returns Record of group ID to metrics
259
+ */
260
+ getResourceMetrics(): Record<string, any>;
261
+ /**
262
+ * Get lifetime stats for resource groups
263
+ *
264
+ * Returns aggregated statistics for strict groups (acquisition times, rejections, etc.)
265
+ *
266
+ * @returns Record of group ID to stats (only strict groups provide stats)
267
+ */
268
+ getResourceStats(): Record<string, any>;
269
+ /**
270
+ * Wait for running tasks, then terminate every worker pool, drop all
271
+ * listeners and clear internal state.
272
+ *
273
+ * Always call this when finished - live workers and the periodic retry timer
274
+ * will otherwise keep the process alive. Pending `onCompleteDescendants()`
275
+ * waits reject.
276
+ */
277
+ shutdown(): Promise<void>;
278
+ }
279
+ //# sourceMappingURL=FyflowScheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FyflowScheduler.d.ts","sourceRoot":"","sources":["../../../core/FyflowScheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { WorkerInstanceExtensions, WorkerInstanceState } from "./workerInterface.js";
2
+ export declare class InlineWrapper extends EventTarget implements WorkerInstanceExtensions, WorkerInstanceState {
3
+ runningTasks: number;
4
+ maxConcurrentTasks: number;
5
+ runningTaskIds: Set<string>;
6
+ runningTaskData: Map<string, {
7
+ id: string;
8
+ payload: any;
9
+ }>;
10
+ idleTimeout: number;
11
+ lastActivityTime: number;
12
+ workerModule: any;
13
+ workerInstance: any;
14
+ scriptUrl: string;
15
+ config: any;
16
+ id: string;
17
+ initializing: boolean;
18
+ state: 'initializing' | 'healthy' | 'busy' | 'failed' | 'terminated';
19
+ lastError?: {
20
+ timestamp: number;
21
+ message: string;
22
+ metadata: any;
23
+ };
24
+ tasksCompleted: number;
25
+ errorCount: number;
26
+ createdAt: number;
27
+ constructor(scriptUrl: string, idleTimeout?: number, maxConcurrentTasks?: number, config?: {});
28
+ canAcceptTask(): boolean;
29
+ getRunningTaskIds(): string[];
30
+ getRunningTasks(): Array<{
31
+ id: string;
32
+ payload: any;
33
+ }>;
34
+ private createTerminateWithError;
35
+ private _handleTerminationRequest;
36
+ private createBaseWorkerContext;
37
+ get idle(): boolean;
38
+ updateActivity(): void;
39
+ _loadWorkerModule(): Promise<any>;
40
+ _createWorkerInstance(): Promise<any>;
41
+ runTask(taskId: string, payload: any): Promise<any>;
42
+ terminate(): Promise<void>;
43
+ _destroyWorkerInstance(): Promise<void>;
44
+ }
45
+ //# sourceMappingURL=inlineWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inlineWrapper.d.ts","sourceRoot":"","sources":["../../../core/inlineWrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAgE,MAAM,sBAAsB,CAAC;AAEnJ,qBAAa,aAAc,SAAQ,WAAY,YAAW,wBAAwB,EAAE,mBAAmB;IACnG,YAAY,SAAK;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAqB;IAChD,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAA;KAAC,CAAC,CAAiD;IACzG,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAc;IACtC,YAAY,EAAE,GAAG,CAAQ;IACzB,cAAc,EAAE,GAAG,CAAQ;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,GAAG,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,UAAS;IAGrB,KAAK,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,YAAY,CAAkB;IACtF,SAAS,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAA;KAAE,CAAC;IAGlE,cAAc,SAAK;IACnB,UAAU,SAAK;IACf,SAAS,EAAE,MAAM,CAAc;gBACnB,SAAS,EAAE,MAAM,EAAE,WAAW,SAAO,EAAE,kBAAkB,SAAI,EAAE,MAAM,KAAK;IAStF,aAAa,IAAI,OAAO;IAKxB,iBAAiB,IAAI,MAAM,EAAE;IAI7B,eAAe,IAAI,KAAK,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAA;KAAC,CAAC;IAKpD,OAAO,CAAC,wBAAwB;IAQhC,OAAO,CAAC,yBAAyB;IA2CjC,OAAO,CAAC,uBAAuB;IAO/B,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,cAAc;IAIR,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC;IAOjC,qBAAqB,IAAI,OAAO,CAAC,GAAG,CAAC;IA2GrC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAkHnD,SAAS;IAWT,sBAAsB;CAiC/B"}
@@ -0,0 +1,59 @@
1
+ import { WorkerInstanceExtensions, WorkerInstanceState } from "./workerInterface.js";
2
+ export declare class ThreadWrapper extends EventTarget implements WorkerInstanceExtensions, WorkerInstanceState {
3
+ worker: Worker | null;
4
+ runningTasks: number;
5
+ maxConcurrentTasks: number;
6
+ idleTimeout: number;
7
+ callbacks: Map<string, {
8
+ resolve: Function;
9
+ reject: Function;
10
+ }>;
11
+ taskStartTimes: Map<string, number>;
12
+ runningTaskData: Map<string, {
13
+ id: string;
14
+ payload: any;
15
+ }>;
16
+ lastActivityTime: number;
17
+ config: any;
18
+ id: string;
19
+ initialized: boolean;
20
+ originalScriptUrl: string;
21
+ initializing: boolean;
22
+ taskQueue: Array<{
23
+ taskId: string;
24
+ payload: any;
25
+ resolve: Function;
26
+ reject: Function;
27
+ }>;
28
+ state: 'initializing' | 'healthy' | 'busy' | 'failed' | 'terminated';
29
+ lastError?: {
30
+ timestamp: number;
31
+ message: string;
32
+ metadata: any;
33
+ };
34
+ tasksCompleted: number;
35
+ errorCount: number;
36
+ createdAt: number;
37
+ private initStartTime;
38
+ private teardownStartTime;
39
+ private pendingTerminationRequest;
40
+ constructor(scriptUrl: string, idleTimeout?: number, maxConcurrentTasks?: number, config?: {});
41
+ canAcceptTask(): boolean;
42
+ getRunningTaskIds(): string[];
43
+ getRunningTasks(): Array<{
44
+ id: string;
45
+ payload: any;
46
+ }>;
47
+ private createTerminateWithError;
48
+ private _handleTerminationRequest;
49
+ private _setupUnexpectedExitDetection;
50
+ private _handleUnexpectedExit;
51
+ private createBaseWorkerContext;
52
+ get idle(): boolean;
53
+ updateActivity(): void;
54
+ _ensureInitialized(): Promise<void>;
55
+ runTask(taskId: string, payload: any): Promise<any>;
56
+ private _processTaskQueue;
57
+ terminate(): Promise<void>;
58
+ }
59
+ //# sourceMappingURL=threadWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threadWrapper.d.ts","sourceRoot":"","sources":["../../../core/threadWrapper.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAA6C,MAAM,sBAAsB,CAAC;AAEhI,qBAAa,aAAc,SAAQ,WAAY,YAAW,wBAAwB,EAAE,mBAAmB;IACnG,MAAM,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC7B,YAAY,SAAK;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;QAAC,OAAO,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,QAAQ,CAAA;KAAC,CAAC,CAA4D;IACzH,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAA6B;IAChE,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAA;KAAC,CAAC,CAAiD;IACzG,gBAAgB,EAAE,MAAM,CAAc;IACtC,MAAM,EAAE,GAAG,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,UAAS;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,UAAS;IAErB,SAAS,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAC;QAAC,OAAO,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,QAAQ,CAAA;KAAC,CAAC,CAAM;IAG3F,KAAK,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,YAAY,CAAkB;IACtF,SAAS,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAA;KAAE,CAAC;IAGlE,cAAc,SAAK;IACnB,UAAU,SAAK;IACf,SAAS,EAAE,MAAM,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,iBAAiB,CAAK;IAG9B,OAAO,CAAC,yBAAyB,CAIjB;gBAGJ,SAAS,EAAE,MAAM,EAAE,WAAW,SAAO,EAAE,kBAAkB,SAAI,EAAE,MAAM,KAAK;IAatF,aAAa,IAAI,OAAO;IAQxB,iBAAiB,IAAI,MAAM,EAAE;IAM7B,eAAe,IAAI,KAAK,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAA;KAAC,CAAC;IAOpD,OAAO,CAAC,wBAAwB;IAoBhC,OAAO,CAAC,yBAAyB;IA2CjC,OAAO,CAAC,6BAA6B;IAsBrC,OAAO,CAAC,qBAAqB;IAwC7B,OAAO,CAAC,uBAAuB;IAO/B,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,cAAc;IAIR,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IA+OnC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IA8BzD,OAAO,CAAC,iBAAiB;IAkBnB,SAAS;CAmChB"}
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Thrown into the task that was running when a worker asked to terminate itself
3
+ * via `context.terminateWithError()`. Catch it to distinguish worker shutdown
4
+ * from an ordinary task failure.
5
+ */
6
+ export declare class WorkerTerminationError extends Error {
7
+ readonly metadata: {
8
+ canRestart?: boolean;
9
+ restartDelay?: number;
10
+ };
11
+ constructor(message: string, metadata?: {
12
+ canRestart?: boolean;
13
+ restartDelay?: number;
14
+ });
15
+ }
16
+ export interface WorkerConfig {
17
+ [key: string]: any;
18
+ }
19
+ /**
20
+ * Messages a worker thread sends back to its ThreadWrapper.
21
+ *
22
+ * `setup_started` / `setup_completed` exist so a threaded worker can report
23
+ * setup timing from inside the thread, letting ThreadWrapper emit the same
24
+ * `worker.setup.*` events an inline worker emits.
25
+ */
26
+ export interface WorkerMessage {
27
+ type: 'init' | 'teardown' | 'result' | 'error' | 'progress' | 'spawn_task' | 'setup_started' | 'setup_completed';
28
+ taskId?: string;
29
+ data?: any;
30
+ timestamp?: number;
31
+ }
32
+ export interface ProgressData {
33
+ progress: number;
34
+ message?: string;
35
+ details?: any;
36
+ }
37
+ export interface SpawnTaskConfig {
38
+ id: string;
39
+ workerType: string;
40
+ payload: any;
41
+ parents?: string[];
42
+ optional?: boolean;
43
+ retryPolicy?: {
44
+ maxRetries: number;
45
+ backoffMs: number;
46
+ };
47
+ workerGroups?: string[];
48
+ }
49
+ /**
50
+ * Worker-level context, passed as the SECOND constructor argument to every
51
+ * worker instance. Forward it to `super(config, workerContext)` - a worker that
52
+ * only accepts `config` silently loses the ability to self-terminate.
53
+ */
54
+ export interface BaseWorkerContext {
55
+ /** Id of this worker instance, as reported by `WorkerManager.getWorkerIds()`. */
56
+ workerId: string;
57
+ /**
58
+ * Ask the pool to tear this worker down, e.g. after detecting a corrupt
59
+ * connection. In-flight tasks are requeued when the pool's
60
+ * `requeueFailedTasks` allows it and `canRestart` is not false.
61
+ */
62
+ terminateWithError: (error: Error, metadata?: {
63
+ canRestart?: boolean;
64
+ restartDelay?: number;
65
+ }) => void;
66
+ }
67
+ /**
68
+ * Task-level context, passed as the second argument to `run()`. Adds per-task
69
+ * capabilities on top of {@link BaseWorkerContext}.
70
+ */
71
+ export interface TaskWorkerContext extends BaseWorkerContext {
72
+ /** Id of the task currently being run. */
73
+ taskId: string;
74
+ /**
75
+ * Report progress as a fraction from 0 to 1 (NOT a percentage). Surfaces as
76
+ * a `task.progress` event on the scheduler.
77
+ */
78
+ sendProgress: (progress: number, message?: string, details?: any) => void;
79
+ /**
80
+ * Create another task while this one runs. The spawned task is a descendant
81
+ * of this one, so `parentTask.onCompleteDescendants()` waits for it.
82
+ *
83
+ * Spawning does not block: the call returns immediately and the task is
84
+ * queued. A spawn naming an unregistered `workerType` emits
85
+ * `task.spawn_failed` and fails only that spawn.
86
+ */
87
+ spawnTask: (config: SpawnTaskConfig) => void;
88
+ }
89
+ export interface WorkerContext extends TaskWorkerContext {
90
+ }
91
+ export interface WorkerInterface {
92
+ /**
93
+ * Initialize the worker with configuration
94
+ * Called once when the worker is first created
95
+ */
96
+ setup?(): Promise<void> | void;
97
+ /**
98
+ * Execute a task with the given payload
99
+ * This is the main method where work is performed
100
+ * @param payload - The task data to process
101
+ * @param context - Task context with progress, spawn, and termination capabilities
102
+ * @returns The result of the task execution
103
+ */
104
+ run(payload: any, context?: TaskWorkerContext): Promise<any> | any;
105
+ /**
106
+ * Clean up resources when the worker is terminated
107
+ * Called when the worker is being shut down
108
+ */
109
+ teardown?(): Promise<void> | void;
110
+ }
111
+ /**
112
+ * Abstract base class for workers providing common functionality
113
+ * Workers can extend this class or implement WorkerInterface directly
114
+ */
115
+ /**
116
+ * Base class for workers. A worker script must `export default` a class.
117
+ *
118
+ * ```typescript
119
+ * export default class MyWorker extends BaseWorker {
120
+ * constructor(config: WorkerConfig = {}, workerContext?: BaseWorkerContext) {
121
+ * super(config, workerContext); // forward BOTH arguments
122
+ * }
123
+ * async setup() {} // required, may be empty
124
+ * async teardown() {} // required, may be empty
125
+ * async run(payload: any, context?: TaskWorkerContext) {
126
+ * return payload.value * 2;
127
+ * }
128
+ * }
129
+ * ```
130
+ *
131
+ * `setup` and `teardown` are abstract: extending without them is a compile
132
+ * error, even when there is nothing to do.
133
+ */
134
+ export declare abstract class BaseWorker implements WorkerInterface {
135
+ protected config: WorkerConfig;
136
+ protected workerContext?: BaseWorkerContext;
137
+ constructor(config?: WorkerConfig, workerContext?: BaseWorkerContext);
138
+ abstract setup(): Promise<void>;
139
+ abstract run(payload: any, context?: TaskWorkerContext): Promise<any> | any;
140
+ abstract teardown(): Promise<void> | void;
141
+ }
142
+ export interface WorkerInstanceState {
143
+ state: 'initializing' | 'healthy' | 'busy' | 'failed' | 'terminated';
144
+ lastError?: {
145
+ timestamp: number;
146
+ message: string;
147
+ metadata: any;
148
+ };
149
+ }
150
+ export interface WorkerInstanceExtensions {
151
+ getRunningTaskIds(): string[];
152
+ getRunningTasks(): Array<{
153
+ id: string;
154
+ payload: any;
155
+ }>;
156
+ canAcceptTask(): boolean;
157
+ }
158
+ export interface WorkerStatus extends WorkerInstanceState {
159
+ id: string;
160
+ tasksCompleted: number;
161
+ errorCount: number;
162
+ uptime: number;
163
+ currentTasks: string[];
164
+ resourcesHeld: string[];
165
+ }
166
+ //# sourceMappingURL=workerInterface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workerInterface.d.ts","sourceRoot":"","sources":["../../../core/workerInterface.ts"],"names":[],"mappings":"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"}