runmq 1.0.1 → 1.0.2
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 +48 -97
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -41,8 +41,8 @@ Publisher → Topic (user.created)
|
|
|
41
41
|
**Key Benefits:**
|
|
42
42
|
- Services remain independent and isolated
|
|
43
43
|
- Each service can fail/retry without affecting others
|
|
44
|
-
- Easy to add new services by subscribing to existing
|
|
45
|
-
-
|
|
44
|
+
- Easy to add new services or processors by subscribing to existing topics
|
|
45
|
+
- Scalable with multiple concurrent workers
|
|
46
46
|
|
|
47
47
|
### 2. Background Processing Pattern
|
|
48
48
|
|
|
@@ -56,7 +56,7 @@ Publisher → Topic (email.send) → Queue: emailWorker → DLQ: emailWorker_dlq
|
|
|
56
56
|
- Simple async job processing
|
|
57
57
|
- Automatic retries for failed jobs
|
|
58
58
|
- Scalable with multiple concurrent workers
|
|
59
|
-
- Dead letter queue for failed
|
|
59
|
+
- Dead letter queue for failed jobs
|
|
60
60
|
|
|
61
61
|
## Quick Start
|
|
62
62
|
|
|
@@ -194,7 +194,8 @@ await runMQ.process<UserCreatedEvent>('user.created', {
|
|
|
194
194
|
|
|
195
195
|
### Scenario: Background Email Processing
|
|
196
196
|
|
|
197
|
-
|
|
197
|
+
The other common pattern is using RunMQ as a job queue for background processing tasks.
|
|
198
|
+
Where there's a publisher queuing jobs, and a worker service processing them asynchronously with retries and DLQ support.
|
|
198
199
|
|
|
199
200
|
```typescript
|
|
200
201
|
import { RunMQ, RunMQMessage } from 'runmq';
|
|
@@ -279,59 +280,7 @@ API Request → Publish Job → Queue (emailWorker)
|
|
|
279
280
|
[Final Failure] → DLQ (emailWorker_dlq)
|
|
280
281
|
```
|
|
281
282
|
|
|
282
|
-
##
|
|
283
|
-
|
|
284
|
-
### Event Choreography with Multiple Events
|
|
285
|
-
|
|
286
|
-
Build complex workflows by publishing new events from processors:
|
|
287
|
-
|
|
288
|
-
```typescript
|
|
289
|
-
// Order Service - publishes order.placed
|
|
290
|
-
await runMQ.process('order.placed', {
|
|
291
|
-
name: 'paymentService',
|
|
292
|
-
consumersCount: 2,
|
|
293
|
-
attempts: 3
|
|
294
|
-
}, async (message) => {
|
|
295
|
-
const payment = await processPayment(message.message);
|
|
296
|
-
|
|
297
|
-
if (payment.success) {
|
|
298
|
-
// Trigger next event in the workflow
|
|
299
|
-
runMQ.publish('payment.completed', {
|
|
300
|
-
orderId: message.message.orderId,
|
|
301
|
-
paymentId: payment.id,
|
|
302
|
-
amount: payment.amount
|
|
303
|
-
}, message.meta.correlationId); // Preserve correlation ID
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
// Inventory Service - reacts to payment.completed
|
|
308
|
-
await runMQ.process('payment.completed', {
|
|
309
|
-
name: 'inventoryService',
|
|
310
|
-
consumersCount: 3,
|
|
311
|
-
attempts: 5
|
|
312
|
-
}, async (message) => {
|
|
313
|
-
await reserveInventory(message.message.orderId);
|
|
314
|
-
|
|
315
|
-
// Trigger next step
|
|
316
|
-
runMQ.publish('inventory.reserved', {
|
|
317
|
-
orderId: message.message.orderId
|
|
318
|
-
}, message.meta.correlationId);
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
// Shipping Service - reacts to inventory.reserved
|
|
322
|
-
await runMQ.process('inventory.reserved', {
|
|
323
|
-
name: 'shippingService',
|
|
324
|
-
consumersCount: 2,
|
|
325
|
-
attempts: 3
|
|
326
|
-
}, async (message) => {
|
|
327
|
-
await scheduleShipment(message.message.orderId);
|
|
328
|
-
|
|
329
|
-
runMQ.publish('order.fulfilled', {
|
|
330
|
-
orderId: message.message.orderId,
|
|
331
|
-
fulfilledAt: new Date().toISOString()
|
|
332
|
-
}, message.meta.correlationId);
|
|
333
|
-
});
|
|
334
|
-
```
|
|
283
|
+
## Features in Detail
|
|
335
284
|
|
|
336
285
|
### Schema Validation
|
|
337
286
|
|
|
@@ -378,6 +327,48 @@ await runMQ.process('order.placed', {
|
|
|
378
327
|
});
|
|
379
328
|
```
|
|
380
329
|
|
|
330
|
+
### Queue Isolation and Naming
|
|
331
|
+
|
|
332
|
+
**Important:** Each processor creates an isolated queue based on its `name` parameter:
|
|
333
|
+
|
|
334
|
+
- Queue name: `{processor.name}`
|
|
335
|
+
- DLQ name: `{processor.name}_dlq`
|
|
336
|
+
|
|
337
|
+
This ensures:
|
|
338
|
+
- ✅ Processors can't interfere with each other
|
|
339
|
+
- ✅ Each processor controls its own retry logic
|
|
340
|
+
- ✅ Failed messages are isolated per processor
|
|
341
|
+
- ✅ Easy to monitor and debug per-processor queues
|
|
342
|
+
|
|
343
|
+
Example:
|
|
344
|
+
```typescript
|
|
345
|
+
// Creates queue: userEmailService and userEmailService_dlq
|
|
346
|
+
await runMQ.process('user.created', { name: 'userEmailService', ... }, handler);
|
|
347
|
+
|
|
348
|
+
// Creates queue: userAnalytics and userAnalytics_dlq
|
|
349
|
+
await runMQ.process('user.created', { name: 'userAnalytics', ... }, handler);
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Custom Logger
|
|
353
|
+
|
|
354
|
+
The default loger uses console, but you can implement your own logger by implementing the `RunMQLogger` interface:
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
import { RunMQLogger } from 'runmq';
|
|
358
|
+
|
|
359
|
+
class CustomLogger implements RunMQLogger {
|
|
360
|
+
log(message: string): void {
|
|
361
|
+
// Your logging implementation
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
error(message: string, error?: any): void {
|
|
365
|
+
// Your error logging implementation
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const runMQ = await RunMQ.start(config, new CustomLogger());
|
|
370
|
+
```
|
|
371
|
+
|
|
381
372
|
## Configuration
|
|
382
373
|
|
|
383
374
|
### Connection Configuration
|
|
@@ -425,46 +416,6 @@ interface RunMQMessageContent<T> {
|
|
|
425
416
|
}
|
|
426
417
|
```
|
|
427
418
|
|
|
428
|
-
## Queue Isolation and Naming
|
|
429
|
-
|
|
430
|
-
**Important:** Each processor creates an isolated queue based on its `name` parameter:
|
|
431
|
-
|
|
432
|
-
- Queue name: `{processor.name}`
|
|
433
|
-
- DLQ name: `{processor.name}_dlq`
|
|
434
|
-
|
|
435
|
-
This ensures:
|
|
436
|
-
- ✅ Processors can't interfere with each other
|
|
437
|
-
- ✅ Each processor controls its own retry logic
|
|
438
|
-
- ✅ Failed messages are isolated per processor
|
|
439
|
-
- ✅ Easy to monitor and debug per-processor queues
|
|
440
|
-
|
|
441
|
-
Example:
|
|
442
|
-
```typescript
|
|
443
|
-
// Creates queue: userEmailService and userEmailService_dlq
|
|
444
|
-
await runMQ.process('user.created', { name: 'userEmailService', ... }, handler);
|
|
445
|
-
|
|
446
|
-
// Creates queue: userAnalytics and userAnalytics_dlq
|
|
447
|
-
await runMQ.process('user.created', { name: 'userAnalytics', ... }, handler);
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
## Custom Logger
|
|
451
|
-
|
|
452
|
-
```typescript
|
|
453
|
-
import { RunMQLogger } from 'runmq';
|
|
454
|
-
|
|
455
|
-
class CustomLogger implements RunMQLogger {
|
|
456
|
-
log(message: string): void {
|
|
457
|
-
// Your logging implementation
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
error(message: string, error?: any): void {
|
|
461
|
-
// Your error logging implementation
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const runMQ = await RunMQ.start(config, new CustomLogger());
|
|
466
|
-
```
|
|
467
|
-
|
|
468
419
|
## License
|
|
469
420
|
|
|
470
421
|
MIT
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "runmq",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
5
|
-
"description": "RunMQ is a reliable message queue library for Node.js built on top of RabbitMQ. Supports async background processing and event-driven messaging for microservices, with automatic retries, schema validation, and DLQ.",
|
|
4
|
+
"version": "1.0.2",
|
|
5
|
+
"description": "RunMQ is a reliable message queue library for Node.js built on top of RabbitMQ Guarantees. Supports async background processing and event-driven messaging for microservices, with automatic retries, schema validation, and DLQ.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"queues",
|
|
8
8
|
"jobs",
|