@elysiumjs/heracles 0.4.3 → 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.
- package/README.md +83 -75
- package/dist/heracles.d.ts +13 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +2 -0
- package/dist/job.d.ts +249 -0
- package/dist/queue.d.ts +247 -0
- package/dist/transport.d.ts +427 -0
- package/dist/transports/redis.transport.d.ts +251 -0
- package/dist/utils.d.ts +34 -0
- package/dist/worker.d.ts +250 -0
- package/dist/workers/base.worker.d.ts +216 -0
- package/dist/workers/redis.worker.d.ts +57 -0
- package/package.json +13 -11
- package/tsconfig.json +34 -33
- package/USAGE.md +0 -527
- package/index.ts +0 -16
- package/src/heracles.ts +0 -68
- package/src/index.ts +0 -28
- package/src/job.ts +0 -413
- package/src/queue.ts +0 -567
- package/src/transport.ts +0 -518
- package/src/transports/redis.transport.ts +0 -1558
- package/src/transports/thread.transport.ts +0 -289
- package/src/utils.ts +0 -61
- package/src/worker.ts +0 -312
- package/src/worker_pool.ts +0 -393
- package/src/workers/base.worker.ts +0 -804
- package/src/workers/redis.worker.ts +0 -523
- package/src/workers/thread.worker.entry.ts +0 -171
- package/src/workers/thread.worker.ts +0 -525
- package/types.d.ts +0 -21
|
@@ -1,525 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2025-present Workbud Technologies Inc. All rights reserved.
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
14
|
-
|
|
15
|
-
import type { Class } from 'type-fest';
|
|
16
|
-
import type { Job } from '../job';
|
|
17
|
-
import type { JobDispatchOptions } from '../queue';
|
|
18
|
-
import type { TransportEvent } from '../transport';
|
|
19
|
-
|
|
20
|
-
import { Service } from '@elysiumjs/core';
|
|
21
|
-
|
|
22
|
-
import { JobStatus } from '../job';
|
|
23
|
-
import { TransportMode } from '../transport';
|
|
24
|
-
import { ThreadTransport } from '../transports/thread.transport';
|
|
25
|
-
import { BaseWorker } from './base.worker';
|
|
26
|
-
|
|
27
|
-
declare const self: Worker;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Worker class that receives jobs from parent thread.
|
|
31
|
-
*/
|
|
32
|
-
export class ThreadWorker extends BaseWorker {
|
|
33
|
-
/**
|
|
34
|
-
* Transport instance used for communication with main thread
|
|
35
|
-
*/
|
|
36
|
-
private readonly transport: ThreadTransport;
|
|
37
|
-
|
|
38
|
-
constructor(queues: string[] = ['default'], id?: string) {
|
|
39
|
-
super(id);
|
|
40
|
-
|
|
41
|
-
this.info(`ThreadWorker ${this.id} started with queues: ${queues.join(', ')}`);
|
|
42
|
-
|
|
43
|
-
// Create transport in consumer mode if in worker thread
|
|
44
|
-
this.transport = new ThreadTransport(TransportMode.CONSUMER);
|
|
45
|
-
this.debug('Created transport in consumer mode');
|
|
46
|
-
|
|
47
|
-
// Only set up message listeners if running in a worker thread
|
|
48
|
-
this.setupMessageListeners();
|
|
49
|
-
|
|
50
|
-
// Initialize the specified queues
|
|
51
|
-
for (const queueName of queues) {
|
|
52
|
-
if (!this.queues.has(queueName)) {
|
|
53
|
-
this.createQueue({ name: queueName });
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Report that the worker is ready if in worker thread
|
|
58
|
-
self.postMessage({
|
|
59
|
-
type: 'worker:ready',
|
|
60
|
-
id: this.id,
|
|
61
|
-
queues: Array.from(this.queues.keys()),
|
|
62
|
-
status: this.status
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Set up message listeners for worker thread
|
|
68
|
-
*/
|
|
69
|
-
private setupMessageListeners(): void {
|
|
70
|
-
self.addEventListener('message', async (event: MessageEvent) => {
|
|
71
|
-
const message = event.data as TransportEvent;
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
await this.handleMessage(message);
|
|
75
|
-
} catch (error: any) {
|
|
76
|
-
this.error(`Error handling message: ${error}`);
|
|
77
|
-
self.postMessage({
|
|
78
|
-
type: 'worker:error',
|
|
79
|
-
error: error.message || String(error),
|
|
80
|
-
workerId: this.id
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// Handle errors
|
|
86
|
-
self.addEventListener('error', (e) => {
|
|
87
|
-
this.trace({ ...e.error, filename: e.filename }, `ThreadWorker ${this.id} error:`);
|
|
88
|
-
self.postMessage({
|
|
89
|
-
type: 'worker:error',
|
|
90
|
-
error: e.error?.message || e.message || 'Unknown error',
|
|
91
|
-
workerId: this.id
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// Handle unhandled promise rejections
|
|
96
|
-
self.addEventListener('unhandledrejection', (e: any) => {
|
|
97
|
-
const error = e.reason || e;
|
|
98
|
-
this.trace(error, `ThreadWorker ${this.id} unhandled rejection:`);
|
|
99
|
-
self.postMessage({
|
|
100
|
-
type: 'worker:error',
|
|
101
|
-
error: error.message || String(error),
|
|
102
|
-
workerId: this.id
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Handle a message from the main thread
|
|
109
|
-
* @public This method is exposed to be called from thread.worker.entry.ts
|
|
110
|
-
*/
|
|
111
|
-
public async handleMessage(message: TransportEvent): Promise<void> {
|
|
112
|
-
switch (message.type) {
|
|
113
|
-
case 'job:process': {
|
|
114
|
-
// Process a new job
|
|
115
|
-
const { job: jobName, args = [], queue = 'default', options } = message;
|
|
116
|
-
this.debug(`ThreadWorker ${this.id} received job ${jobName} for queue ${queue}`);
|
|
117
|
-
await this.handleProcessJob(jobName, args, queue, {
|
|
118
|
-
...options,
|
|
119
|
-
scheduledFor: new Date(options?.scheduledFor ?? Date.now())
|
|
120
|
-
});
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
case 'job:cancel': {
|
|
125
|
-
// Cancel a job
|
|
126
|
-
const { jobId, queue = 'default' } = message;
|
|
127
|
-
const canceled = await this.cancelJob(jobId, queue);
|
|
128
|
-
this.sendStatusUpdate({
|
|
129
|
-
type: 'job:canceled',
|
|
130
|
-
jobId,
|
|
131
|
-
queue,
|
|
132
|
-
success: canceled,
|
|
133
|
-
count: canceled ? 1 : 0
|
|
134
|
-
});
|
|
135
|
-
break;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
case 'job:cancelAll': {
|
|
139
|
-
// Cancel all jobs in a queue
|
|
140
|
-
const { queue = 'default' } = message;
|
|
141
|
-
const canceledCount = await this.cancelAllJobs(queue);
|
|
142
|
-
this.sendStatusUpdate({
|
|
143
|
-
type: 'job:canceled',
|
|
144
|
-
queue,
|
|
145
|
-
count: canceledCount
|
|
146
|
-
});
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
case 'job:status': {
|
|
151
|
-
// Get job status
|
|
152
|
-
const { jobId, queue = 'default' } = message;
|
|
153
|
-
const job = await this.getJob(jobId, queue);
|
|
154
|
-
|
|
155
|
-
if (job) {
|
|
156
|
-
this.sendStatusUpdate({
|
|
157
|
-
type: 'job:status',
|
|
158
|
-
jobId,
|
|
159
|
-
queue,
|
|
160
|
-
status: job.status,
|
|
161
|
-
error: job.lastError?.message,
|
|
162
|
-
retries: job.retries,
|
|
163
|
-
startedAt: job.startedAt?.toISOString(),
|
|
164
|
-
completedAt: job.completedAt?.toISOString()
|
|
165
|
-
});
|
|
166
|
-
} else {
|
|
167
|
-
this.sendStatusUpdate({
|
|
168
|
-
type: 'job:status',
|
|
169
|
-
jobId,
|
|
170
|
-
queue,
|
|
171
|
-
status: 'unknown'
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
break;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
case 'worker:register': {
|
|
178
|
-
// Add new queues to this worker
|
|
179
|
-
if (message.queues?.length) {
|
|
180
|
-
for (const queueName of message.queues) {
|
|
181
|
-
if (!this.queues.has(queueName)) {
|
|
182
|
-
await this.createQueue({ name: queueName });
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Send updated worker info
|
|
187
|
-
this.sendWorkerStatusUpdate();
|
|
188
|
-
}
|
|
189
|
-
break;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
case 'worker:unregister': {
|
|
193
|
-
// Stop the worker
|
|
194
|
-
await this.stop();
|
|
195
|
-
|
|
196
|
-
// Notify main thread that worker is stopping
|
|
197
|
-
this.sendStatusUpdate({
|
|
198
|
-
type: 'worker:status',
|
|
199
|
-
workerId: this.id,
|
|
200
|
-
status: 'stopped',
|
|
201
|
-
queues: Array.from(this.queues.keys()),
|
|
202
|
-
processing: 0,
|
|
203
|
-
waiting: 0
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
break;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Process the next job in a queue
|
|
213
|
-
*/
|
|
214
|
-
public async processNextJob(queueName: string): Promise<void> {
|
|
215
|
-
const queue = this.queues.get(queueName);
|
|
216
|
-
if (!queue || queue.paused || queue.processing >= queue.options.concurrency!) {
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const queuedJob = queue.jobs.shift();
|
|
221
|
-
if (!queuedJob) {
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (queuedJob.job.status === JobStatus.CANCELLED) {
|
|
226
|
-
this.info(`Skipping cancelled job ${queuedJob.job.id}`);
|
|
227
|
-
this.sendStatusUpdate({
|
|
228
|
-
type: 'job:status',
|
|
229
|
-
jobId: queuedJob.job.id,
|
|
230
|
-
queue: queueName,
|
|
231
|
-
status: JobStatus.CANCELLED
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
this.processQueueJobs(queueName);
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// Add to active jobs
|
|
239
|
-
queue.activeJobs.set(queuedJob.job.id, queuedJob);
|
|
240
|
-
queue.processing++;
|
|
241
|
-
|
|
242
|
-
// Send job started status update
|
|
243
|
-
try {
|
|
244
|
-
await this.transport.updateJobStatus(queuedJob.job.id, queuedJob.job.dispatchId, queueName, {
|
|
245
|
-
status: JobStatus.RUNNING,
|
|
246
|
-
startedAt: new Date().toISOString()
|
|
247
|
-
});
|
|
248
|
-
} catch (error) {
|
|
249
|
-
this.error(`Error updating job status to RUNNING: ${error}`);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
try {
|
|
253
|
-
this.debug(`Processing job ${queuedJob.job.id} from queue '${queueName}'`);
|
|
254
|
-
await queuedJob.job.run();
|
|
255
|
-
|
|
256
|
-
// Handle job completion based on status
|
|
257
|
-
if (queuedJob.job.status === JobStatus.FAILED) {
|
|
258
|
-
// Determine max retries - use job-specific setting if available, otherwise queue setting
|
|
259
|
-
const maxRetries =
|
|
260
|
-
queuedJob.maxRetries !== undefined ? queuedJob.maxRetries : queue.options.maxRetries!;
|
|
261
|
-
|
|
262
|
-
if (queuedJob.retries < maxRetries) {
|
|
263
|
-
// Schedule for retry
|
|
264
|
-
queuedJob.retries++;
|
|
265
|
-
queuedJob.job.incrementRetries();
|
|
266
|
-
this.warning(
|
|
267
|
-
`Job ${queuedJob.job.id} failed, retrying (${queuedJob.retries}/${maxRetries})`
|
|
268
|
-
);
|
|
269
|
-
|
|
270
|
-
// Determine retry delay - use job-specific setting if available, otherwise queue setting
|
|
271
|
-
const retryDelay =
|
|
272
|
-
queuedJob.retryDelay !== undefined ? queuedJob.retryDelay : queue.options.retryDelay!;
|
|
273
|
-
|
|
274
|
-
// Set scheduled time for retry
|
|
275
|
-
const retryTime = new Date();
|
|
276
|
-
retryTime.setMilliseconds(retryTime.getMilliseconds() + retryDelay);
|
|
277
|
-
queuedJob.scheduledFor = retryTime;
|
|
278
|
-
|
|
279
|
-
// Send status update for scheduled retry
|
|
280
|
-
try {
|
|
281
|
-
await this.transport.updateJobStatus(queuedJob.job.id, queuedJob.job.id, queueName, {
|
|
282
|
-
status: JobStatus.SCHEDULED_FOR_RETRY,
|
|
283
|
-
error: queuedJob.job.lastError?.message,
|
|
284
|
-
retries: queuedJob.retries
|
|
285
|
-
});
|
|
286
|
-
} catch (error) {
|
|
287
|
-
this.error(`Error updating job status to SCHEDULED_FOR_RETRY: ${error}`);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Schedule the retry
|
|
291
|
-
setTimeout(async () => {
|
|
292
|
-
if (queuedJob.job.status !== JobStatus.CANCELLED) {
|
|
293
|
-
queue.jobs.push(queuedJob);
|
|
294
|
-
this.processQueueJobs(queueName);
|
|
295
|
-
} else {
|
|
296
|
-
this.info(`Skipping cancelled job ${queuedJob.job.id} during retry delay`);
|
|
297
|
-
try {
|
|
298
|
-
await this.transport.updateJobStatus(
|
|
299
|
-
queuedJob.job.id,
|
|
300
|
-
queuedJob.job.id,
|
|
301
|
-
queueName,
|
|
302
|
-
{
|
|
303
|
-
status: JobStatus.CANCELLED
|
|
304
|
-
}
|
|
305
|
-
);
|
|
306
|
-
} catch (error) {
|
|
307
|
-
this.error(`Error updating job status to CANCELLED: ${error}`);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}, retryDelay);
|
|
311
|
-
} else {
|
|
312
|
-
// Job failed permanently after all retries
|
|
313
|
-
const maxRetries =
|
|
314
|
-
queuedJob.maxRetries !== undefined ? queuedJob.maxRetries : queue.options.maxRetries!;
|
|
315
|
-
this.error(
|
|
316
|
-
`Job ${queuedJob.job.id} failed after ${queuedJob.retries} retries (max: ${maxRetries})`
|
|
317
|
-
);
|
|
318
|
-
|
|
319
|
-
// Send final failure status
|
|
320
|
-
const completedAt = queuedJob.job.completedAt?.toISOString() || new Date().toISOString();
|
|
321
|
-
try {
|
|
322
|
-
await this.transport.updateJobStatus(queuedJob.job.id, queuedJob.job.id, queueName, {
|
|
323
|
-
status: JobStatus.FAILED,
|
|
324
|
-
error: queuedJob.job.lastError?.message,
|
|
325
|
-
completedAt
|
|
326
|
-
});
|
|
327
|
-
} catch (error) {
|
|
328
|
-
this.error(`Error updating job status to FAILED: ${error}`);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
if (queue.options.pauseOnError) {
|
|
332
|
-
this.pause(queueName);
|
|
333
|
-
this.warning(`Queue '${queueName}' paused due to job failure`);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
} else if (queuedJob.job.status === JobStatus.COMPLETED) {
|
|
337
|
-
// Job completed successfully
|
|
338
|
-
this.success(`Job ${queuedJob.job.id} completed successfully`);
|
|
339
|
-
|
|
340
|
-
// Send completion status
|
|
341
|
-
const completedAt = queuedJob.job.completedAt?.toISOString() || new Date().toISOString();
|
|
342
|
-
try {
|
|
343
|
-
await this.transport.updateJobStatus(queuedJob.job.id, queuedJob.job.id, queueName, {
|
|
344
|
-
status: JobStatus.COMPLETED,
|
|
345
|
-
completedAt
|
|
346
|
-
});
|
|
347
|
-
} catch (error) {
|
|
348
|
-
this.error(`Error updating job status to COMPLETED: ${error}`);
|
|
349
|
-
}
|
|
350
|
-
} else if (queuedJob.job.status === JobStatus.CANCELLED) {
|
|
351
|
-
// Job was cancelled while running
|
|
352
|
-
this.info(`Job ${queuedJob.job.id} cancelled while running`);
|
|
353
|
-
|
|
354
|
-
// Send cancellation status
|
|
355
|
-
const completedAt = queuedJob.job.completedAt?.toISOString() || new Date().toISOString();
|
|
356
|
-
try {
|
|
357
|
-
await this.transport.updateJobStatus(queuedJob.job.id, queuedJob.job.id, queueName, {
|
|
358
|
-
status: JobStatus.CANCELLED,
|
|
359
|
-
completedAt
|
|
360
|
-
});
|
|
361
|
-
} catch (error) {
|
|
362
|
-
this.error(`Error updating job status to CANCELLED: ${error}`);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
} catch (error: any) {
|
|
366
|
-
// Handle unexpected errors during job execution
|
|
367
|
-
this.error(`Unexpected error processing job ${queuedJob.job.id}: ${error}`);
|
|
368
|
-
|
|
369
|
-
// Send error status using transport if available
|
|
370
|
-
const completedAt = new Date().toISOString();
|
|
371
|
-
const errorMsg = error.message || String(error);
|
|
372
|
-
if (this.transport && typeof this.transport.updateJobStatus === 'function') {
|
|
373
|
-
await this.transport.updateJobStatus(queuedJob.job.id, queuedJob.job.id, queueName, {
|
|
374
|
-
status: JobStatus.FAILED,
|
|
375
|
-
error: errorMsg,
|
|
376
|
-
completedAt
|
|
377
|
-
});
|
|
378
|
-
} else {
|
|
379
|
-
this.sendStatusUpdate({
|
|
380
|
-
type: 'job:result',
|
|
381
|
-
jobId: queuedJob.job.id,
|
|
382
|
-
queue: queueName,
|
|
383
|
-
status: JobStatus.FAILED,
|
|
384
|
-
error: errorMsg,
|
|
385
|
-
completedAt
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
if (queue.options.pauseOnError) {
|
|
390
|
-
this.pause(queueName);
|
|
391
|
-
this.warning(`Queue '${queueName}' paused due to unexpected error`);
|
|
392
|
-
}
|
|
393
|
-
} finally {
|
|
394
|
-
// Remove job from active jobs and decrement processing count
|
|
395
|
-
queue.activeJobs.delete(queuedJob.job.id);
|
|
396
|
-
queue.processing--;
|
|
397
|
-
|
|
398
|
-
// Send worker status update
|
|
399
|
-
this.sendWorkerStatusUpdate();
|
|
400
|
-
|
|
401
|
-
// Process next job if available
|
|
402
|
-
this.processQueueJobs(queueName);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* Create a job from a job class name and add it to a queue
|
|
408
|
-
*/
|
|
409
|
-
private async handleProcessJob(
|
|
410
|
-
jobName: string,
|
|
411
|
-
args: any[],
|
|
412
|
-
queue: string = 'default',
|
|
413
|
-
options?: Partial<JobDispatchOptions>
|
|
414
|
-
): Promise<void> {
|
|
415
|
-
this.debug(`Processing job ${jobName} in ThreadWorker for queue ${queue}`);
|
|
416
|
-
try {
|
|
417
|
-
// Get job class from service container
|
|
418
|
-
const JobClass = Service.get(jobName) as Class<Job>;
|
|
419
|
-
if (!JobClass) {
|
|
420
|
-
this.error(`Job class ${jobName} not found`);
|
|
421
|
-
throw new Error(`Job class ${jobName} not found`);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
// Create job instance
|
|
425
|
-
const job = new JobClass(...(args || []));
|
|
426
|
-
job.queueName = queue;
|
|
427
|
-
|
|
428
|
-
// Prepare job options
|
|
429
|
-
const jobOptions: JobDispatchOptions = options || {};
|
|
430
|
-
|
|
431
|
-
// Convert ISO string date to Date object if needed
|
|
432
|
-
if (jobOptions.scheduledFor && typeof jobOptions.scheduledFor === 'string') {
|
|
433
|
-
jobOptions.scheduledFor = new Date(jobOptions.scheduledFor);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// Set initial job status
|
|
437
|
-
const initialStatus =
|
|
438
|
-
jobOptions.scheduledFor && jobOptions.scheduledFor > new Date()
|
|
439
|
-
? JobStatus.SCHEDULED_FOR_RETRY
|
|
440
|
-
: JobStatus.PENDING;
|
|
441
|
-
|
|
442
|
-
try {
|
|
443
|
-
await this.transport.updateJobStatus(job.id, job.dispatchId, queue, {
|
|
444
|
-
status: initialStatus,
|
|
445
|
-
createdAt: new Date().toISOString()
|
|
446
|
-
});
|
|
447
|
-
} catch (error) {
|
|
448
|
-
this.error(`Error setting initial job status: ${error}`);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
// Add job to queue with options
|
|
452
|
-
await this.addJob(job, queue, jobOptions);
|
|
453
|
-
|
|
454
|
-
// Send job received confirmation
|
|
455
|
-
this.sendStatusUpdate({
|
|
456
|
-
type: 'job:received',
|
|
457
|
-
jobId: job.id,
|
|
458
|
-
queue
|
|
459
|
-
});
|
|
460
|
-
} catch (error: any) {
|
|
461
|
-
// Log and report error
|
|
462
|
-
this.trace(
|
|
463
|
-
error,
|
|
464
|
-
`Error while adding job '${jobName}' to queue '${queue}' with worker ${this.id}`
|
|
465
|
-
);
|
|
466
|
-
|
|
467
|
-
this.sendStatusUpdate({
|
|
468
|
-
type: 'job:error',
|
|
469
|
-
jobId: `error_${Date.now()}`,
|
|
470
|
-
jobName,
|
|
471
|
-
queue,
|
|
472
|
-
error: error.message || String(error)
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
/**
|
|
478
|
-
* Send a status update to the main thread (legacy method)
|
|
479
|
-
* @deprecated Use transport.updateJobStatus instead
|
|
480
|
-
*/
|
|
481
|
-
private sendStatusUpdate(message: any): void {
|
|
482
|
-
this.warning(`Using deprecated sendStatusUpdate. Use transport.updateJobStatus instead`);
|
|
483
|
-
self.postMessage(message);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
/**
|
|
487
|
-
* Send worker status update to main thread
|
|
488
|
-
*/
|
|
489
|
-
private sendWorkerStatusUpdate(): void {
|
|
490
|
-
// Calculate waiting and processing counts
|
|
491
|
-
let waiting = 0;
|
|
492
|
-
let processing = 0;
|
|
493
|
-
|
|
494
|
-
for (const queue of this.queues.values()) {
|
|
495
|
-
waiting += queue.jobs.length;
|
|
496
|
-
processing += queue.processing;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
// Send status update
|
|
500
|
-
self.postMessage({
|
|
501
|
-
type: 'worker:status',
|
|
502
|
-
workerId: this.id,
|
|
503
|
-
queues: Array.from(this.queues.keys()),
|
|
504
|
-
status: this.status as string,
|
|
505
|
-
processing,
|
|
506
|
-
waiting
|
|
507
|
-
});
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
/**
|
|
511
|
-
* Override start method to send status update
|
|
512
|
-
*/
|
|
513
|
-
public async start(): Promise<void> {
|
|
514
|
-
await super.start();
|
|
515
|
-
this.sendWorkerStatusUpdate();
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/**
|
|
519
|
-
* Override stop method to send status update
|
|
520
|
-
*/
|
|
521
|
-
public async stop(force: boolean = false): Promise<void> {
|
|
522
|
-
await super.stop(force);
|
|
523
|
-
this.sendWorkerStatusUpdate();
|
|
524
|
-
}
|
|
525
|
-
}
|
package/types.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2025-present Workbud Technologies Inc. All rights reserved.
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
14
|
-
|
|
15
|
-
declare namespace globalThis {
|
|
16
|
-
/**
|
|
17
|
-
* A macro indicating if the code is running from a build.
|
|
18
|
-
* @author Axel Nana <axel.nana@workbud.com>
|
|
19
|
-
*/
|
|
20
|
-
var ELYSIUM_BUILD: boolean;
|
|
21
|
-
}
|