@elysiumjs/heracles 0.4.4 → 0.5.1

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.
@@ -0,0 +1,247 @@
1
+ import type { EventHandler } from '@elysiumjs/core';
2
+ import type { JobClass, JobOverlapBehavior } from './job';
3
+ import type { JobStatusInfo, TransportClass, TransportEvent } from './transport';
4
+ import { InteractsWithConsole } from '@elysiumjs/core';
5
+ import { Job, JobStatus } from './job';
6
+ /**
7
+ * Options for dispatching a job to a queue.
8
+ * @author Axel Nana <axel.nana@workbud.com>
9
+ */
10
+ export type JobDispatchOptions = {
11
+ /**
12
+ * Schedule the job to run at a specific time.
13
+ */
14
+ scheduledFor?: Date;
15
+ /**
16
+ * Priority of this job (lower number = higher priority).
17
+ * @default 10
18
+ */
19
+ priority?: number;
20
+ /**
21
+ * Maximum number of retries for this job.
22
+ * Overrides both the job class and queue settings.
23
+ */
24
+ maxRetries?: number;
25
+ /**
26
+ * Delay between retries in milliseconds.
27
+ * Overrides both the job class and queue settings.
28
+ */
29
+ retryDelay?: number;
30
+ /**
31
+ * Optional job ID to use for this dispatch.
32
+ * If not provided, a unique ID will be generated.
33
+ */
34
+ jobId?: string;
35
+ /**
36
+ * A unique ID for this specific dispatch of the job.
37
+ * If not provided, one will be generated.
38
+ */
39
+ dispatchId?: string;
40
+ /**
41
+ * Defines how the job handles overlap with other instances of the same job ID.
42
+ * Overrides the setting from the job class.
43
+ */
44
+ overlapBehavior?: JobOverlapBehavior;
45
+ /**
46
+ * When using NO_OVERLAP behavior, specifies the delay in milliseconds
47
+ * between sequential executions of jobs with the same ID.
48
+ * Overrides the setting from the job class.
49
+ */
50
+ overlapDelay?: number;
51
+ };
52
+ /**
53
+ * Configuration options for a Queue.
54
+ * @author Axel Nana <axel.nana@workbud.com>
55
+ */
56
+ export type QueueOptions = {
57
+ /**
58
+ * The name of the queue.
59
+ */
60
+ name: string;
61
+ /**
62
+ * The transport class to use for this queue.
63
+ */
64
+ transport: TransportClass;
65
+ /**
66
+ * The maximum number of concurrent jobs to process in this queue.
67
+ * @default 1
68
+ */
69
+ concurrency?: number;
70
+ /**
71
+ * The maximum number of retries for failed jobs.
72
+ * @default 0
73
+ */
74
+ maxRetries?: number;
75
+ /**
76
+ * The delay in milliseconds between retries.
77
+ * @default 1000
78
+ */
79
+ retryDelay?: number;
80
+ /**
81
+ * Whether to pause processing when an error occurs.
82
+ * @default false
83
+ */
84
+ pauseOnError?: boolean;
85
+ /**
86
+ * Configuration options for the transport.
87
+ * This is passed to the transport constructor.
88
+ */
89
+ transportOptions?: Record<string, any>;
90
+ };
91
+ /**
92
+ * Generated ID when dispatching jobs in queues.
93
+ * @author Axel Nana <axel.nana@workbud.com>
94
+ */
95
+ export type JobDispatchId = {
96
+ /**
97
+ * The job ID.
98
+ */
99
+ jobId: string;
100
+ /**
101
+ * The dispatch ID.
102
+ */
103
+ dispatchId: string;
104
+ };
105
+ /**
106
+ * Queue class for dispatching jobs to workers.
107
+ * @author Axel Nana <axel.nana@icloud.com>
108
+ */
109
+ export declare class Queue extends InteractsWithConsole {
110
+ /**
111
+ * Map of all registered queues.
112
+ */
113
+ private static queues;
114
+ /**
115
+ * Checks whether a queue exists.
116
+ * @param name The name of the queue.
117
+ * @returns `true` if the queue exists, `false` otherwise.
118
+ */
119
+ static exists(name: string): boolean;
120
+ /**
121
+ * Get a queue by name, or create it if it doesn't exist.
122
+ *
123
+ * @param name The name of the queue.
124
+ * @param config Optional configuration for the queue if it needs to be created.
125
+ * @returns The queue instance.
126
+ */
127
+ static get(name: string, config?: Omit<QueueOptions, 'name'>): Queue;
128
+ /**
129
+ * Get all registered queues.
130
+ *
131
+ * @returns A map of all registered queues.
132
+ */
133
+ static getAll(): Map<string, Queue>;
134
+ /**
135
+ * The name of this queue
136
+ */
137
+ readonly name: string;
138
+ /**
139
+ * The transport used by this queue
140
+ */
141
+ private readonly transport;
142
+ /**
143
+ * The transport class for this queue.
144
+ */
145
+ private transportClass?;
146
+ /**
147
+ * The transport options for this queue. These are passed to the transport constructor.
148
+ */
149
+ private transportOptions?;
150
+ /**
151
+ * The queue configuration options.
152
+ */
153
+ private options;
154
+ /**
155
+ * Array of job IDs currently being processed
156
+ */
157
+ private jobs;
158
+ /**
159
+ * Creates a new Queue instance.
160
+ *
161
+ * @param config The queue configuration.
162
+ */
163
+ private constructor();
164
+ on<TData, TSource = any>(event: TransportEvent['type'], handler: EventHandler<TData, TSource> | never): void;
165
+ once<TData, TSource = any>(event: TransportEvent['type'], handler: EventHandler<TData, TSource> | never): void;
166
+ private emit;
167
+ /**
168
+ * Handle messages from the transport
169
+ *
170
+ * @param message The message from the transport
171
+ */
172
+ private handleTransportMessage;
173
+ /**
174
+ * Update the status of a job.
175
+ *
176
+ * @param jobId The ID of the job.
177
+ * @param dispatchID The dispatch ID of the job.
178
+ * @param status The new status information.
179
+ */
180
+ private updateJobStatus;
181
+ /**
182
+ * Dispatch a job to this queue
183
+ *
184
+ * @param name The name of the job to dispatch
185
+ * @param args The arguments to pass to the job constructor
186
+ * @param options Optional dispatch options
187
+ * @returns A promise that resolves to the created job instance
188
+ */
189
+ dispatch<T extends Job, TClass extends JobClass<T> = JobClass<T>>(job: TClass, name: string, args?: ConstructorParameters<TClass>, options?: JobDispatchOptions): Promise<JobDispatchId>;
190
+ /**
191
+ * Cancel a job in this queue.
192
+ *
193
+ * @param id The ID of the dispatched job to cancel.
194
+ * @returns A promise that resolves to true if the job was found and canceled.
195
+ */
196
+ cancelJob(id: JobDispatchId): Promise<boolean>;
197
+ /**
198
+ * Cancel all jobs in this queue.
199
+ *
200
+ * @returns A promise that resolves to the number of jobs canceled.
201
+ */
202
+ cancelAllJobs(): Promise<number>;
203
+ /**
204
+ * Get the status of a job.
205
+ *
206
+ * @param id The ID of the job.
207
+ * @returns A promise that resolves to the job status or null if not found
208
+ */
209
+ getJobStatus(id: JobDispatchId): Promise<JobStatusInfo | null>;
210
+ /**
211
+ * Get all jobs in this queue
212
+ *
213
+ * @returns An array of job IDs
214
+ */
215
+ getAllJobs(): Array<JobDispatchId>;
216
+ /**
217
+ * Get jobs by status
218
+ *
219
+ * @param status The status to filter by
220
+ * @returns An array of jobs with the specified status
221
+ */
222
+ getJobsByStatus(status: JobStatus): Promise<JobDispatchId[]>;
223
+ /**
224
+ * Start the queue's transport.
225
+ *
226
+ * @returns A promise that resolves when the transport has started.
227
+ */
228
+ start(): Promise<void>;
229
+ /**
230
+ * Stop the queue's transport.
231
+ *
232
+ * @returns A promise that resolves when the transport has stopped.
233
+ */
234
+ stop(): Promise<void>;
235
+ /**
236
+ * Get the queue options.
237
+ *
238
+ * @returns The queue options.
239
+ */
240
+ getOptions(): QueueOptions;
241
+ /**
242
+ * Update the queue options.
243
+ *
244
+ * @param options The new options
245
+ */
246
+ updateOptions(options: Partial<QueueOptions>): void;
247
+ }
@@ -0,0 +1,427 @@
1
+ import type { JobDispatchOptions } from './queue';
2
+ /**
3
+ * Discriminated union of all events carried by a transport channel.
4
+ * @author Axel Nana <axel.nana@workbud.com>
5
+ */
6
+ export type TransportEvent = TransportProcessMessage | TransportCancelMessage | TransportCancelAllMessage | TransportJobStatusMessage | TransportWorkerStatusMessage | TransportJobResultMessage | TransportWorkerRegistrationMessage | TransportWorkerReadyMessage | TransportJobUpdateMessage;
7
+ /**
8
+ * Message sent to process a job.
9
+ * @author Axel Nana <axel.nana@workbud.com>
10
+ */
11
+ export type TransportProcessMessage = {
12
+ /**
13
+ * The type of message.
14
+ */
15
+ type: 'job:process';
16
+ /**
17
+ * The name of the job to process. It should match the name of the job class,
18
+ * or the alias in the Service container.
19
+ */
20
+ job: string;
21
+ /**
22
+ * Arguments to pass to the job constructor.
23
+ */
24
+ args: unknown[];
25
+ /**
26
+ * The name of the queue to process the job.
27
+ */
28
+ queue: string;
29
+ /**
30
+ * The ID of the job.
31
+ * When creating a new job, this will be generated if not provided.
32
+ */
33
+ jobId: string;
34
+ /**
35
+ * The dispatch ID of the job.
36
+ * This is unique for each dispatch, even if the job ID is the same.
37
+ */
38
+ dispatchId: string;
39
+ /**
40
+ * Optional job dispatch configuration.
41
+ * Note: scheduledFor is transmitted as ISO string instead of Date object.
42
+ */
43
+ options?: Omit<JobDispatchOptions, 'scheduledFor'> & {
44
+ /**
45
+ * When the job should be scheduled to run (ISO string).
46
+ */
47
+ scheduledFor?: string;
48
+ };
49
+ };
50
+ /**
51
+ * Message sent to cancel a job (by ID).
52
+ * @author Axel Nana <axel.nana@workbud.com>
53
+ */
54
+ export type TransportCancelMessage = {
55
+ /**
56
+ * The type of message.
57
+ */
58
+ type: 'job:cancel';
59
+ /**
60
+ * The ID of the job to cancel.
61
+ */
62
+ jobId: string;
63
+ /**
64
+ * The ID of the dispatch.
65
+ */
66
+ dispatchId: string;
67
+ /**
68
+ * The name of the queue where the job is located.
69
+ */
70
+ queue: string;
71
+ };
72
+ /**
73
+ * Message sent to cancel all jobs.
74
+ * @author Axel Nana <axel.nana@workbud.com>
75
+ */
76
+ export type TransportCancelAllMessage = {
77
+ /**
78
+ * The type of message.
79
+ */
80
+ type: 'job:cancelAll';
81
+ /**
82
+ * The name of the queue to cancel all jobs in.
83
+ */
84
+ queue: string;
85
+ };
86
+ /**
87
+ * Message with job status information.
88
+ * @author Axel Nana <axel.nana@workbud.com>
89
+ */
90
+ export type TransportJobStatusMessage = {
91
+ /**
92
+ * The type of message.
93
+ */
94
+ type: 'job:status';
95
+ /**
96
+ * The ID of the job.
97
+ */
98
+ jobId: string;
99
+ /**
100
+ * The ID of the dispatch that created the job.
101
+ */
102
+ dispatchId: string;
103
+ /**
104
+ * The name of the queue the job belongs to.
105
+ */
106
+ queue: string;
107
+ /**
108
+ * The current status of the job.
109
+ */
110
+ status: string;
111
+ /**
112
+ * The error message if the job failed.
113
+ */
114
+ error?: string;
115
+ /**
116
+ * The number of retries attempted.
117
+ */
118
+ retries?: number;
119
+ /**
120
+ * Timestamp when the job started.
121
+ */
122
+ startedAt?: string;
123
+ /**
124
+ * Timestamp when the job completed or failed.
125
+ */
126
+ completedAt?: string;
127
+ /**
128
+ * Timestamp when this status update was created.
129
+ */
130
+ updatedAt?: string;
131
+ /**
132
+ * Timestamp when the job was created.
133
+ */
134
+ createdAt?: string;
135
+ };
136
+ /**
137
+ * Message with worker status information.
138
+ * @author Axel Nana <axel.nana@workbud.com>
139
+ */
140
+ export type TransportWorkerStatusMessage = {
141
+ /**
142
+ * The type of message.
143
+ */
144
+ type: 'worker:status';
145
+ /**
146
+ * The ID of the worker.
147
+ */
148
+ workerId: string;
149
+ /**
150
+ * The queues this worker is handling.
151
+ */
152
+ queues: string[];
153
+ /**
154
+ * The current status of the worker.
155
+ */
156
+ status: 'active' | 'paused' | 'draining' | 'stopped';
157
+ /**
158
+ * The number of jobs currently being processed by this worker.
159
+ */
160
+ processing: number;
161
+ /**
162
+ * The number of jobs waiting in this worker's queues.
163
+ */
164
+ waiting: number;
165
+ };
166
+ /**
167
+ * Message with job results.
168
+ * @author Axel Nana <axel.nana@workbud.com>
169
+ */
170
+ export type TransportJobResultMessage = {
171
+ /**
172
+ * The type of message.
173
+ */
174
+ type: 'job:result';
175
+ /**
176
+ * The ID of the job.
177
+ */
178
+ jobId: string;
179
+ /**
180
+ * The ID of the dispatch that created the job.
181
+ */
182
+ dispatchId: string;
183
+ /**
184
+ * The name of the queue the job belongs to.
185
+ */
186
+ queue: string;
187
+ /**
188
+ * The final status of the job.
189
+ */
190
+ status: string;
191
+ /**
192
+ * The error message if the job failed.
193
+ */
194
+ error?: string;
195
+ /**
196
+ * Timestamp when the job completed or failed.
197
+ */
198
+ completedAt: string;
199
+ /**
200
+ * Timestamp when this update was created.
201
+ */
202
+ updatedAt?: string;
203
+ /**
204
+ * The number of retries that were attempted.
205
+ */
206
+ retries?: number;
207
+ };
208
+ /**
209
+ * Message for worker registration.
210
+ * @author Axel Nana <axel.nana@workbud.com>
211
+ */
212
+ export type TransportWorkerRegistrationMessage = {
213
+ /**
214
+ * The type of message.
215
+ */
216
+ type: 'worker:register' | 'worker:unregister';
217
+ /**
218
+ * The ID of the worker.
219
+ */
220
+ workerId: string;
221
+ /**
222
+ * The queues the worker handles (for registration).
223
+ */
224
+ queues?: string[];
225
+ };
226
+ /**
227
+ * Message indicating a worker is ready.
228
+ * @author Axel Nana <axel.nana@workbud.com>
229
+ */
230
+ export type TransportWorkerReadyMessage = {
231
+ /**
232
+ * The type of message.
233
+ */
234
+ type: 'worker:ready';
235
+ /**
236
+ * The ID of the worker.
237
+ */
238
+ id: string;
239
+ /**
240
+ * The queues the worker handles.
241
+ */
242
+ queues: string[];
243
+ /**
244
+ * The timestamp when the worker became ready.
245
+ */
246
+ timestamp?: number;
247
+ /**
248
+ * The worker status.
249
+ */
250
+ status?: string;
251
+ };
252
+ /**
253
+ * Job status information.
254
+ * @author Axel Nana <axel.nana@workbud.com>
255
+ */
256
+ export interface JobStatusInfo {
257
+ /**
258
+ * The ID of the job.
259
+ */
260
+ jobId: string;
261
+ /**
262
+ * The dispatch ID of the job.
263
+ * This uniquely identifies a specific dispatch of a job, even if the job ID is the same.
264
+ */
265
+ dispatchId: string;
266
+ /**
267
+ * The name of the queue the job belongs to.
268
+ */
269
+ queue: string;
270
+ /**
271
+ * The current status of the job.
272
+ */
273
+ status: string;
274
+ /**
275
+ * The error message if the job failed.
276
+ */
277
+ error?: string;
278
+ /**
279
+ * The number of retries attempted.
280
+ */
281
+ retries: number;
282
+ /**
283
+ * Timestamp when the job was created.
284
+ */
285
+ createdAt: string;
286
+ /**
287
+ * Timestamp when the job started.
288
+ */
289
+ startedAt?: string;
290
+ /**
291
+ * Timestamp when the job completed or failed.
292
+ */
293
+ completedAt?: string;
294
+ /**
295
+ * Timestamp when this status was last updated.
296
+ */
297
+ updatedAt?: string;
298
+ /**
299
+ * The original message ID in the Redis stream (internal use).
300
+ */
301
+ messageId?: string;
302
+ }
303
+ /**
304
+ * Indicates what mode a Transport is operating in.
305
+ * @author Axel Nana <axel.nana@workbud.com>
306
+ */
307
+ export declare enum TransportMode {
308
+ /**
309
+ * Listens for jobs/events from the transport (e.g., worker).
310
+ */
311
+ CONSUMER = "consumer",
312
+ /**
313
+ * Actively pushes jobs/events to the transport (e.g., dispatcher).
314
+ */
315
+ PRODUCER = "producer"
316
+ }
317
+ /**
318
+ * Message specific to job status updates.
319
+ * @author Axel Nana <axel.nana@workbud.com>
320
+ */
321
+ export type TransportJobUpdateMessage = {
322
+ /**
323
+ * The type of message.
324
+ */
325
+ type: 'job:update';
326
+ /**
327
+ * The ID of the job.
328
+ */
329
+ jobId: string;
330
+ /**
331
+ * The ID of the dispatch.
332
+ */
333
+ dispatchId: string;
334
+ /**
335
+ * The name of the queue the job belongs to.
336
+ */
337
+ queue: string;
338
+ /**
339
+ * The current status of the job.
340
+ */
341
+ status: string;
342
+ /**
343
+ * Updates to the job status fields.
344
+ */
345
+ updates: Partial<JobStatusInfo>;
346
+ /**
347
+ * Whether to create a new entry if the job doesn't exist.
348
+ */
349
+ createIfNotExist?: boolean;
350
+ };
351
+ /**
352
+ * Interface for any transport layer that delivers job events between queue and worker.
353
+ * @author Axel Nana <axel.nana@workbud.com>
354
+ */
355
+ export interface Transport {
356
+ /**
357
+ * Starts the transport.
358
+ *
359
+ * This method should initialize the transport and mark it as ready to receive messages.
360
+ */
361
+ start(): Promise<void> | void;
362
+ /**
363
+ * Stops the transport.
364
+ *
365
+ * This method should stop the transport and mark it as stopped.
366
+ */
367
+ stop(): Promise<void> | void;
368
+ /**
369
+ * Sends a message over the transport.
370
+ *
371
+ * @param message The message to send.
372
+ * @returns A promise that resolves when the message has been sent.
373
+ */
374
+ send(message: TransportEvent): Promise<void> | void;
375
+ /**
376
+ * Registers a callback for receiving messages from the transport.
377
+ *
378
+ * @param handler The handler function to call when a message is received.
379
+ */
380
+ onMessage(handler: (message: TransportEvent) => void | Promise<void>): void;
381
+ /**
382
+ * Gets the current status of a job.
383
+ *
384
+ * @param jobId The ID of the job to get the status for.
385
+ * @param dispatchId The ID generated for the dispatch of the job.
386
+ * @param queueName The name of the queue the job belongs to.
387
+ * @returns A promise that resolves with the current job status.
388
+ */
389
+ getJobStatus(jobId: string, dispatchId: string, queueName: string): Promise<JobStatusInfo>;
390
+ /**
391
+ * Registers a worker with the transport.
392
+ *
393
+ * @param workerId The ID of the worker.
394
+ * @param queues The queues the worker handles.
395
+ * @returns A promise that resolves when the worker is registered.
396
+ */
397
+ registerWorker(workerId: string, queues: string[]): Promise<void>;
398
+ /**
399
+ * Unregisters a worker from the transport.
400
+ *
401
+ * @param workerId The ID of the worker to unregister.
402
+ * @returns A promise that resolves when the worker is unregistered.
403
+ */
404
+ unregisterWorker(workerId: string): Promise<void>;
405
+ /**
406
+ * Updates a job status directly without creating a new message.
407
+ *
408
+ * @param jobId The ID of the job to update.
409
+ * @param queueName The name of the queue the job belongs to.
410
+ * @param updates The status updates to apply.
411
+ * @returns A promise that resolves when the job is updated.
412
+ */
413
+ updateJobStatus(jobId: string, dispatchId: string, queueName: string, updates: Partial<JobStatusInfo>): Promise<void>;
414
+ }
415
+ /**
416
+ * Type signature for a transport constructor.
417
+ * @author Axel Nana <axel.nana@workbud.com>
418
+ */
419
+ export type TransportClass<T extends Transport = Transport> = {
420
+ /**
421
+ * Creates a new transport instance.
422
+ *
423
+ * @param mode The mode of the transport (consumer or producer).
424
+ * @param options The options to pass to the transport.
425
+ */
426
+ new (mode: TransportMode, options?: Record<string, any>): T;
427
+ };