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.
- package/AGENTS.md +577 -0
- package/LICENSE +21 -0
- package/README.md +415 -0
- package/dist/browser/index.js +2378 -0
- package/dist/node/index.js +2380 -0
- package/dist/types/core/FyflowScheduler.d.ts +279 -0
- package/dist/types/core/FyflowScheduler.d.ts.map +1 -0
- package/dist/types/core/inlineWrapper.d.ts +45 -0
- package/dist/types/core/inlineWrapper.d.ts.map +1 -0
- package/dist/types/core/threadWrapper.d.ts +59 -0
- package/dist/types/core/threadWrapper.d.ts.map +1 -0
- package/dist/types/core/workerInterface.d.ts +166 -0
- package/dist/types/core/workerInterface.d.ts.map +1 -0
- package/dist/types/core/workerManager.d.ts +141 -0
- package/dist/types/core/workerManager.d.ts.map +1 -0
- package/dist/types/core/workerWrapper.d.ts +2 -0
- package/dist/types/core/workerWrapper.d.ts.map +1 -0
- package/dist/types/core/workerWrapperUrl.bundled.d.ts +2 -0
- package/dist/types/core/workerWrapperUrl.bundled.d.ts.map +1 -0
- package/dist/types/core/workerWrapperUrl.d.ts +2 -0
- package/dist/types/core/workerWrapperUrl.d.ts.map +1 -0
- package/dist/types/groups/concurrentLimitGroup.d.ts +33 -0
- package/dist/types/groups/concurrentLimitGroup.d.ts.map +1 -0
- package/dist/types/groups/keyedRateLimitGroup.d.ts +98 -0
- package/dist/types/groups/keyedRateLimitGroup.d.ts.map +1 -0
- package/dist/types/groups/rateLimitGroup.d.ts +79 -0
- package/dist/types/groups/rateLimitGroup.d.ts.map +1 -0
- package/dist/types/groups/resourceGroup.d.ts +41 -0
- package/dist/types/groups/resourceGroup.d.ts.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- 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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"}
|