redis-smq 8.0.0-rc.15 → 8.0.0-rc.17
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/CHANGELOG.md +42 -0
- package/README.md +18 -15
- package/dist/index.cjs +232 -106
- package/dist/index.d.cts +197 -139
- package/dist/index.d.ts +197 -139
- package/dist/index.js +234 -114
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
## [8.0.0-rc.17](https://github.com/weyoss/redis-smq/compare/v8.0.0-rc.16...v8.0.0-rc.17) (2024-01-30)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Documentation
|
|
7
|
+
|
|
8
|
+
* add missing error classes ([753331e](https://github.com/weyoss/redis-smq/commit/753331e5ce4fb239cb29b3ae4c3246ba185b4d94))
|
|
9
|
+
* simplify and unify class/method naming and referencing ([0299b31](https://github.com/weyoss/redis-smq/commit/0299b314e843c28d52e2f767ace150e39652287c))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Codebase Refactoring
|
|
13
|
+
|
|
14
|
+
* improve MessageHandler error handling ([957d257](https://github.com/weyoss/redis-smq/commit/957d257e66cce6faaf9dad5bf949cdd1198cfae8))
|
|
15
|
+
|
|
16
|
+
## [8.0.0-rc.16](https://github.com/weyoss/redis-smq/compare/v8.0.0-rc.15...v8.0.0-rc.16) (2024-01-28)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* allow running/sandboxing message handlers using worker threads ([53095bd](https://github.com/weyoss/redis-smq/commit/53095bd2689ccb2f701365bafb4ef8e550da82b3))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Bug Fixes
|
|
25
|
+
|
|
26
|
+
* export message handler errors ([26d2689](https://github.com/weyoss/redis-smq/commit/26d26890da139d88c46ce220e3dda3d9c8e03aee))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Documentation
|
|
30
|
+
|
|
31
|
+
* **ConsumeMessageWorker:** update docs and clean up ([140322e](https://github.com/weyoss/redis-smq/commit/140322e3520ee3db905ea977a159064f339aa7d2))
|
|
32
|
+
* fix broken links ([aad9010](https://github.com/weyoss/redis-smq/commit/aad9010e70ed332b154f4fbdcb8ac657a14fe6b9))
|
|
33
|
+
* update messages and queues documentation ([7c3d06e](https://github.com/weyoss/redis-smq/commit/7c3d06ed3765ffc14dfece4f725241aa4535e1e7))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Codebase Refactoring
|
|
37
|
+
|
|
38
|
+
* **ConsumeMessageWorker:** improve typings ([66c6ca9](https://github.com/weyoss/redis-smq/commit/66c6ca948677f76d496fe0b988bd195e1a7108a2))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
### Tests
|
|
42
|
+
|
|
43
|
+
* allow running/sandboxing message handlers using worker threads ([79e6886](https://github.com/weyoss/redis-smq/commit/79e688674ed11ec34ce2f74d5f15c8eefa129767))
|
|
44
|
+
|
|
3
45
|
## [8.0.0-rc.15](https://github.com/weyoss/redis-smq/compare/v8.0.0-rc.14...v8.0.0-rc.15) (2024-01-25)
|
|
4
46
|
|
|
5
47
|
|
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@ RedisSMQ is a Node.js library for queuing messages (aka jobs) and processing the
|
|
|
27
27
|
* Supports [Point-2-Point](docs/queue-delivery-models.md#point-2-point-delivery-model) and [Pub/Sub](docs/queue-delivery-models.md#pubsub-delivery-model) [delivery models](docs/queue-delivery-models.md).
|
|
28
28
|
* Both [delivery models](docs/queue-delivery-models.md) are reliable. For cases of failure, while delivering/consuming messages, [at-least-once](docs/api/classes/ProducibleMessage.md#setretrythreshold) and [at-most-once](docs/api/classes/ProducibleMessage.md#setretrythreshold) modes may be configured.
|
|
29
29
|
* [3 queuing strategies](docs/queues.md): [FIFO queues](docs/queues.md#fifo-first-in-first-out-queues), [LIFO queues](docs/queues.md#lifo-last-in-first-out-queues), and [Priority Queues](docs/queues.md#priority-queues).
|
|
30
|
+
* [Message Handler Worker Threads](docs/message-handler-worker-threads.md) which allow sandboxing and running your message handler from a separate isolated thread and without affecting the performance of other message handlers from the same consumer.
|
|
30
31
|
* Messages can be [set to expire](docs/api/classes/ProducibleMessage.md#setttl) when not delivered within a given amount of time or to have a [consumption timeout](docs/api/classes/ProducibleMessage.md#setconsumetimeout) while being in process.
|
|
31
32
|
* Queues may be [rate Limited](docs/queue-rate-limiting.md) to control the rate at which the messages are consumed.
|
|
32
33
|
* Has a builtin [scheduler](docs/scheduling-messages.md) allowing messages [to be delayed](docs/api/classes/ProducibleMessage.md#setscheduleddelay), [to be delivered for N times](docs/api/classes/ProducibleMessage.md#setscheduledrepeat) with an optional [period between deliveries](docs/api/classes/ProducibleMessage.md#setscheduledrepeatperiod), or simply [to be scheduled using CRON expressions](docs/api/classes/ProducibleMessage.md#setscheduledcron).
|
|
@@ -66,42 +67,44 @@ A queue is responsible for holding messages which are produced by producers and
|
|
|
66
67
|
### Creating a queue
|
|
67
68
|
|
|
68
69
|
```javascript
|
|
69
|
-
const { Queue, EQueueType, EQueueDeliveryModel } = require('redis-smq');
|
|
70
|
-
|
|
71
70
|
const queue = new Queue();
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
queue.save('my_queue', EQueueType.LIFO_QUEUE, EQueueDeliveryModel.POINT_TO_POINT, (err) => {
|
|
72
|
+
if (err) console.error(err)
|
|
73
|
+
});
|
|
75
74
|
```
|
|
76
75
|
|
|
77
76
|
In the example above we are defining a [LIFO queue](docs/queues.md#lifo-last-in-first-out-queues) with a [POINT-2-POINT delivery model](docs/queue-delivery-models.md#point-2-point-delivery-model).
|
|
78
77
|
|
|
78
|
+
See [Queues](docs/queues.md) for more details.
|
|
79
|
+
|
|
79
80
|
### Producing a message
|
|
80
81
|
|
|
81
82
|
```javascript
|
|
82
|
-
const { Producer, ProducibleMessage } = require('redis-smq');
|
|
83
|
-
|
|
84
|
-
const producer = new Producer();
|
|
85
|
-
|
|
86
83
|
const msg = new ProducibleMessage();
|
|
87
84
|
msg.setQueue('my_queue').setBody('Hello Word!')
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
producer.produce(msg, (err, ids) => {
|
|
86
|
+
if (err) console.error(err);
|
|
87
|
+
else console.log(`Produced message IDs are: ${ids.join(', ')}`)
|
|
88
|
+
});
|
|
90
89
|
```
|
|
91
90
|
|
|
91
|
+
See [Producing Messages](docs/producing-messages.md) for more details.
|
|
92
|
+
|
|
92
93
|
### Consuming a message
|
|
93
94
|
|
|
94
95
|
```javascript
|
|
95
|
-
const { Consumer } = require('redis-smq');
|
|
96
|
-
|
|
97
96
|
const consumer = new Consumer();
|
|
98
97
|
const messageHandler = (msg, cb) => {
|
|
99
|
-
console.log(msg.
|
|
98
|
+
console.log(msg.body);
|
|
100
99
|
cb();
|
|
101
100
|
}
|
|
102
|
-
consumer.consume('my_queue', messageHandler, (err) =>
|
|
101
|
+
consumer.consume('my_queue', messageHandler, (err) => {
|
|
102
|
+
if (err) console.error(err);
|
|
103
|
+
});
|
|
103
104
|
```
|
|
104
105
|
|
|
106
|
+
See [Consuming Messages](docs/consuming-messages.md) for more details.
|
|
107
|
+
|
|
105
108
|
## Documentation
|
|
106
109
|
|
|
107
110
|
See [RedisSMQ Docs](docs/README.md) for more details.
|
package/dist/index.cjs
CHANGED
|
@@ -69,6 +69,10 @@ __export(redis_smq_exports, {
|
|
|
69
69
|
ConsumerGroups: () => ConsumerGroups,
|
|
70
70
|
ConsumerInvalidGroupIdError: () => ConsumerInvalidGroupIdError,
|
|
71
71
|
ConsumerMessageHandlerAlreadyExistsError: () => ConsumerMessageHandlerAlreadyExistsError,
|
|
72
|
+
ConsumerMessageHandlerError: () => ConsumerMessageHandlerError,
|
|
73
|
+
ConsumerMessageHandlerFileError: () => ConsumerMessageHandlerFileError,
|
|
74
|
+
ConsumerMessageHandlerFilenameExtensionError: () => ConsumerMessageHandlerFilenameExtensionError,
|
|
75
|
+
ConsumerMessageHandlerWorkerError: () => ConsumerMessageHandlerWorkerError,
|
|
72
76
|
EConsumeMessageDeadLetterCause: () => EConsumeMessageDeadLetterCause,
|
|
73
77
|
EConsumeMessageUnacknowledgedCause: () => EConsumeMessageUnacknowledgedCause,
|
|
74
78
|
EExchangeType: () => EExchangeType,
|
|
@@ -78,6 +82,8 @@ __export(redis_smq_exports, {
|
|
|
78
82
|
EQueueDeliveryModel: () => EQueueDeliveryModel,
|
|
79
83
|
EQueueProperty: () => EQueueProperty,
|
|
80
84
|
EQueueType: () => EQueueType,
|
|
85
|
+
EWorkerThreadMessageCodeConsume: () => EWorkerThreadMessageCodeConsume,
|
|
86
|
+
EWorkerThreadMessageCodeExit: () => EWorkerThreadMessageCodeExit,
|
|
81
87
|
ExchangeDirect: () => ExchangeDirect,
|
|
82
88
|
ExchangeError: () => ExchangeError,
|
|
83
89
|
ExchangeFanOut: () => ExchangeFanOut,
|
|
@@ -437,6 +443,22 @@ var EConsumeMessageUnacknowledgedCause = /* @__PURE__ */ ((EConsumeMessageUnackn
|
|
|
437
443
|
return EConsumeMessageUnacknowledgedCause3;
|
|
438
444
|
})(EConsumeMessageUnacknowledgedCause || {});
|
|
439
445
|
|
|
446
|
+
// types/consumer/consume-message-worker.ts
|
|
447
|
+
var EWorkerThreadMessageCodeExit = /* @__PURE__ */ ((EWorkerThreadMessageCodeExit2) => {
|
|
448
|
+
EWorkerThreadMessageCodeExit2[EWorkerThreadMessageCodeExit2["WORKER_DATA_REQUIRED"] = 100] = "WORKER_DATA_REQUIRED";
|
|
449
|
+
EWorkerThreadMessageCodeExit2[EWorkerThreadMessageCodeExit2["INVALID_HANDLER_TYPE"] = 101] = "INVALID_HANDLER_TYPE";
|
|
450
|
+
EWorkerThreadMessageCodeExit2[EWorkerThreadMessageCodeExit2["HANDLER_IMPORT_ERROR"] = 102] = "HANDLER_IMPORT_ERROR";
|
|
451
|
+
EWorkerThreadMessageCodeExit2[EWorkerThreadMessageCodeExit2["UNCAUGHT_EXCEPTION"] = 103] = "UNCAUGHT_EXCEPTION";
|
|
452
|
+
EWorkerThreadMessageCodeExit2[EWorkerThreadMessageCodeExit2["TERMINATED"] = 104] = "TERMINATED";
|
|
453
|
+
return EWorkerThreadMessageCodeExit2;
|
|
454
|
+
})(EWorkerThreadMessageCodeExit || {});
|
|
455
|
+
var EWorkerThreadMessageCodeConsume = /* @__PURE__ */ ((EWorkerThreadMessageCodeConsume2) => {
|
|
456
|
+
EWorkerThreadMessageCodeConsume2[EWorkerThreadMessageCodeConsume2["OK"] = 200] = "OK";
|
|
457
|
+
EWorkerThreadMessageCodeConsume2[EWorkerThreadMessageCodeConsume2["MESSAGE_PROCESSING_ERROR"] = 201] = "MESSAGE_PROCESSING_ERROR";
|
|
458
|
+
EWorkerThreadMessageCodeConsume2[EWorkerThreadMessageCodeConsume2["MESSAGE_PROCESSING_CAUGHT_ERROR"] = 202] = "MESSAGE_PROCESSING_CAUGHT_ERROR";
|
|
459
|
+
return EWorkerThreadMessageCodeConsume2;
|
|
460
|
+
})(EWorkerThreadMessageCodeConsume || {});
|
|
461
|
+
|
|
440
462
|
// types/exchange/common.ts
|
|
441
463
|
var EExchangeType = /* @__PURE__ */ ((EExchangeType2) => {
|
|
442
464
|
EExchangeType2[EExchangeType2["DIRECT"] = 0] = "DIRECT";
|
|
@@ -674,6 +696,41 @@ var MessageDeleteError = class extends MessageError {
|
|
|
674
696
|
}
|
|
675
697
|
};
|
|
676
698
|
|
|
699
|
+
// src/lib/consumer/message-handler/errors/consumer-message-handler.error.ts
|
|
700
|
+
var ConsumerMessageHandlerError = class extends ConsumerError {
|
|
701
|
+
constructor(msg) {
|
|
702
|
+
super(msg);
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
|
|
706
|
+
// src/lib/consumer/message-handler/errors/consumer-message-handler-worker.error.ts
|
|
707
|
+
var ConsumerMessageHandlerWorkerError = class extends ConsumerMessageHandlerError {
|
|
708
|
+
constructor(msg) {
|
|
709
|
+
var _a;
|
|
710
|
+
const { code, error } = msg;
|
|
711
|
+
const messageStr = `Error code: ${(_a = EWorkerThreadMessageCodeExit[code]) != null ? _a : EWorkerThreadMessageCodeConsume[code]}.${error ? ` Cause: ${error.name}(${error.message})` : ""}`;
|
|
712
|
+
super(messageStr);
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
// src/lib/consumer/message-handler/errors/consumer-message-handler-filename-extension.error.ts
|
|
717
|
+
var ConsumerMessageHandlerFilenameExtensionError = class extends ConsumerMessageHandlerError {
|
|
718
|
+
constructor() {
|
|
719
|
+
super(
|
|
720
|
+
`Message handler filename must ends with a '.js' or '.cjs' extension depending on your project settings.`
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
// src/lib/consumer/message-handler/errors/consumer-message-handler-file.error.ts
|
|
726
|
+
var ConsumerMessageHandlerFileError = class extends ConsumerMessageHandlerError {
|
|
727
|
+
constructor() {
|
|
728
|
+
super(
|
|
729
|
+
`Make sure the message handler filename is an absolute file path pointing to an existing file in your project. `
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
|
|
677
734
|
// src/lib/consumer/consumer-heartbeat.ts
|
|
678
735
|
var os = __toESM(require("os"), 1);
|
|
679
736
|
var import_redis_smq_common10 = require("redis-smq-common");
|
|
@@ -981,6 +1038,8 @@ var Base = class extends import_redis_smq_common11.EventEmitter {
|
|
|
981
1038
|
};
|
|
982
1039
|
|
|
983
1040
|
// src/lib/consumer/message-handler/message-handler.ts
|
|
1041
|
+
var import_fs = require("fs");
|
|
1042
|
+
var import_path3 = __toESM(require("path"), 1);
|
|
984
1043
|
var import_uuid4 = require("uuid");
|
|
985
1044
|
|
|
986
1045
|
// src/lib/consumer/message-handler/processing-queue.ts
|
|
@@ -1419,6 +1478,13 @@ var MessageEnvelope = class {
|
|
|
1419
1478
|
consumerGroupId: this.getConsumerGroupId()
|
|
1420
1479
|
};
|
|
1421
1480
|
}
|
|
1481
|
+
transfer() {
|
|
1482
|
+
return __spreadProps(__spreadValues({}, this.toJSON()), {
|
|
1483
|
+
id: this.getId(),
|
|
1484
|
+
messageState: this.getMessageState().toJSON(),
|
|
1485
|
+
status: this.getStatus()
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1422
1488
|
hasRetryThresholdExceeded() {
|
|
1423
1489
|
const threshold = this.producibleMessage.getRetryThreshold();
|
|
1424
1490
|
return this.messageState.getAttempts() + 1 >= threshold;
|
|
@@ -2679,87 +2745,76 @@ var DequeueMessage = class {
|
|
|
2679
2745
|
// src/lib/consumer/message-handler/consume-message.ts
|
|
2680
2746
|
var import_redis_smq_common24 = require("redis-smq-common");
|
|
2681
2747
|
|
|
2682
|
-
// src/lib/message/
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
return msg.getDestinationQueue();
|
|
2708
|
-
},
|
|
2709
|
-
getPriority() {
|
|
2710
|
-
return msg.producibleMessage.getPriority();
|
|
2711
|
-
},
|
|
2712
|
-
getBody() {
|
|
2713
|
-
return msg.producibleMessage.getBody();
|
|
2714
|
-
},
|
|
2715
|
-
getTTL() {
|
|
2716
|
-
return msg.producibleMessage.getTTL();
|
|
2717
|
-
},
|
|
2718
|
-
getRetryThreshold() {
|
|
2719
|
-
return msg.producibleMessage.getRetryThreshold();
|
|
2720
|
-
},
|
|
2721
|
-
getRetryDelay() {
|
|
2722
|
-
return msg.producibleMessage.getRetryDelay();
|
|
2723
|
-
},
|
|
2724
|
-
getConsumeTimeout() {
|
|
2725
|
-
return msg.producibleMessage.getConsumeTimeout();
|
|
2726
|
-
},
|
|
2727
|
-
getCreatedAt() {
|
|
2728
|
-
return msg.producibleMessage.getCreatedAt();
|
|
2729
|
-
},
|
|
2730
|
-
getScheduledRepeat() {
|
|
2731
|
-
return msg.producibleMessage.getScheduledRepeat();
|
|
2732
|
-
},
|
|
2733
|
-
getScheduledRepeatPeriod() {
|
|
2734
|
-
return msg.producibleMessage.getScheduledRepeatPeriod();
|
|
2735
|
-
},
|
|
2736
|
-
getScheduledCRON() {
|
|
2737
|
-
return msg.producibleMessage.getScheduledCRON();
|
|
2738
|
-
},
|
|
2739
|
-
getScheduledDelay() {
|
|
2740
|
-
return msg.producibleMessage.getScheduledDelay();
|
|
2741
|
-
},
|
|
2742
|
-
getFanOut() {
|
|
2743
|
-
return msg.producibleMessage.getFanOut();
|
|
2744
|
-
},
|
|
2745
|
-
getTopic() {
|
|
2746
|
-
return msg.producibleMessage.getTopic();
|
|
2747
|
-
},
|
|
2748
|
-
toJSON() {
|
|
2749
|
-
return msg.toJSON();
|
|
2750
|
-
},
|
|
2751
|
-
getExchange() {
|
|
2752
|
-
return msg.getExchange();
|
|
2753
|
-
},
|
|
2754
|
-
getConsumerGroupId() {
|
|
2755
|
-
return msg.getConsumerGroupId();
|
|
2748
|
+
// src/lib/consumer/message-handler/consume-message-worker.ts
|
|
2749
|
+
var import_path2 = __toESM(require("path"), 1);
|
|
2750
|
+
var import_worker_threads = require("worker_threads");
|
|
2751
|
+
var ConsumeMessageWorker = class {
|
|
2752
|
+
constructor(messageHandlerFilename) {
|
|
2753
|
+
this.messageHandlerThread = null;
|
|
2754
|
+
this.messageHandlerFilename = messageHandlerFilename;
|
|
2755
|
+
}
|
|
2756
|
+
getMessageHandlerThread() {
|
|
2757
|
+
if (!this.messageHandlerThread) {
|
|
2758
|
+
this.messageHandlerThread = new import_worker_threads.Worker(
|
|
2759
|
+
import_path2.default.resolve(__dirname, "./consume-message-worker-thread.js"),
|
|
2760
|
+
{
|
|
2761
|
+
workerData: this.messageHandlerFilename
|
|
2762
|
+
}
|
|
2763
|
+
);
|
|
2764
|
+
this.messageHandlerThread.on("messageerror", (err) => {
|
|
2765
|
+
console.error(err);
|
|
2766
|
+
});
|
|
2767
|
+
this.messageHandlerThread.on("error", (err) => {
|
|
2768
|
+
console.error(err);
|
|
2769
|
+
});
|
|
2770
|
+
this.messageHandlerThread.on("exit", () => {
|
|
2771
|
+
this.messageHandlerThread = null;
|
|
2772
|
+
});
|
|
2756
2773
|
}
|
|
2757
|
-
|
|
2758
|
-
}
|
|
2774
|
+
return this.messageHandlerThread;
|
|
2775
|
+
}
|
|
2776
|
+
consume(message, cb) {
|
|
2777
|
+
const worker = this.getMessageHandlerThread();
|
|
2778
|
+
const cleanUp = () => {
|
|
2779
|
+
worker.removeListener("message", onMessage).removeListener("exit", onExit);
|
|
2780
|
+
};
|
|
2781
|
+
const onMessage = (msg) => {
|
|
2782
|
+
cleanUp();
|
|
2783
|
+
if (msg.code !== 200 /* OK */) {
|
|
2784
|
+
console.error(`ConsumerMessageHandlerWorkerError`, msg);
|
|
2785
|
+
cb(new ConsumerMessageHandlerWorkerError(msg));
|
|
2786
|
+
} else
|
|
2787
|
+
cb();
|
|
2788
|
+
};
|
|
2789
|
+
const onExit = () => {
|
|
2790
|
+
cleanUp();
|
|
2791
|
+
const msg = {
|
|
2792
|
+
code: 104 /* TERMINATED */,
|
|
2793
|
+
error: null
|
|
2794
|
+
};
|
|
2795
|
+
console.error("ConsumerMessageHandlerWorkerError", msg);
|
|
2796
|
+
cb(new ConsumerMessageHandlerWorkerError(msg));
|
|
2797
|
+
};
|
|
2798
|
+
worker.once("message", onMessage);
|
|
2799
|
+
worker.once("exit", onExit);
|
|
2800
|
+
worker.postMessage(message);
|
|
2801
|
+
}
|
|
2802
|
+
quit(cb) {
|
|
2803
|
+
const callback = () => {
|
|
2804
|
+
this.messageHandlerThread = null;
|
|
2805
|
+
cb();
|
|
2806
|
+
};
|
|
2807
|
+
if (this.messageHandlerThread) {
|
|
2808
|
+
this.messageHandlerThread.terminate().then(callback).catch(callback);
|
|
2809
|
+
} else
|
|
2810
|
+
cb();
|
|
2811
|
+
}
|
|
2812
|
+
};
|
|
2759
2813
|
|
|
2760
2814
|
// src/lib/consumer/message-handler/consume-message.ts
|
|
2761
2815
|
var ConsumeMessage = class {
|
|
2762
2816
|
constructor(messageHandler, redisClient2, logger3) {
|
|
2817
|
+
this.consumeMessageWorker = null;
|
|
2763
2818
|
this.redisClient = redisClient2;
|
|
2764
2819
|
this.messageHandler = messageHandler;
|
|
2765
2820
|
this.queue = messageHandler.getQueue();
|
|
@@ -2843,6 +2898,20 @@ var ConsumeMessage = class {
|
|
|
2843
2898
|
}
|
|
2844
2899
|
);
|
|
2845
2900
|
}
|
|
2901
|
+
getConsumeMessageWorker(messageHandlerFilename) {
|
|
2902
|
+
if (!this.consumeMessageWorker) {
|
|
2903
|
+
this.consumeMessageWorker = new ConsumeMessageWorker(
|
|
2904
|
+
messageHandlerFilename
|
|
2905
|
+
);
|
|
2906
|
+
}
|
|
2907
|
+
return this.consumeMessageWorker;
|
|
2908
|
+
}
|
|
2909
|
+
invokeMessageHandler(messageHandler, msg, cb) {
|
|
2910
|
+
if (typeof messageHandler === "string") {
|
|
2911
|
+
this.getConsumeMessageWorker(messageHandler).consume(msg, cb);
|
|
2912
|
+
} else
|
|
2913
|
+
messageHandler(msg, cb);
|
|
2914
|
+
}
|
|
2846
2915
|
consumeMessage(msg) {
|
|
2847
2916
|
let isTimeout = false;
|
|
2848
2917
|
let timer = null;
|
|
@@ -2884,8 +2953,9 @@ var ConsumeMessage = class {
|
|
|
2884
2953
|
}
|
|
2885
2954
|
}
|
|
2886
2955
|
};
|
|
2887
|
-
this.
|
|
2888
|
-
|
|
2956
|
+
this.invokeMessageHandler(
|
|
2957
|
+
this.messageHandler.getHandler(),
|
|
2958
|
+
msg.transfer(),
|
|
2889
2959
|
onConsumed
|
|
2890
2960
|
);
|
|
2891
2961
|
} catch (error) {
|
|
@@ -2905,6 +2975,12 @@ var ConsumeMessage = class {
|
|
|
2905
2975
|
} else
|
|
2906
2976
|
this.consumeMessage(message);
|
|
2907
2977
|
}
|
|
2978
|
+
quit(cb) {
|
|
2979
|
+
if (this.consumeMessageWorker) {
|
|
2980
|
+
this.consumeMessageWorker.quit(cb);
|
|
2981
|
+
} else
|
|
2982
|
+
cb();
|
|
2983
|
+
}
|
|
2908
2984
|
};
|
|
2909
2985
|
|
|
2910
2986
|
// src/lib/consumer/message-handler/message-handler.ts
|
|
@@ -2920,7 +2996,7 @@ var MessageHandler = class extends import_redis_smq_common25.EventEmitter {
|
|
|
2920
2996
|
this.dequeueRedisClient = dequeueRedisClient;
|
|
2921
2997
|
this.sharedRedisClient = sharedRedisClient;
|
|
2922
2998
|
this.handler = messageHandler;
|
|
2923
|
-
this.powerSwitch = new import_redis_smq_common25.PowerSwitch();
|
|
2999
|
+
this.powerSwitch = new import_redis_smq_common25.PowerSwitch(false);
|
|
2924
3000
|
this.logger = logger3;
|
|
2925
3001
|
this.dequeueMessage = new DequeueMessage(this, dequeueRedisClient);
|
|
2926
3002
|
this.consumeMessage = new ConsumeMessage(this, dequeueRedisClient, logger3);
|
|
@@ -3010,6 +3086,17 @@ var MessageHandler = class extends import_redis_smq_common25.EventEmitter {
|
|
|
3010
3086
|
shutdownDequeueClient(cb) {
|
|
3011
3087
|
this.dequeueRedisClient.halt(cb);
|
|
3012
3088
|
}
|
|
3089
|
+
forceShutDown(cb) {
|
|
3090
|
+
this.powerSwitch.rollback();
|
|
3091
|
+
import_redis_smq_common25.async.waterfall(
|
|
3092
|
+
[
|
|
3093
|
+
(cb2) => this.dequeueMessage.quit(cb2),
|
|
3094
|
+
(cb2) => this.consumeMessage.quit(cb2),
|
|
3095
|
+
(cb2) => this.shutdownDequeueClient(cb2)
|
|
3096
|
+
],
|
|
3097
|
+
cb
|
|
3098
|
+
);
|
|
3099
|
+
}
|
|
3013
3100
|
handleError(err) {
|
|
3014
3101
|
if (this.powerSwitch.isRunning() || this.powerSwitch.isGoingUp()) {
|
|
3015
3102
|
this.emit("error", err);
|
|
@@ -3020,35 +3107,63 @@ var MessageHandler = class extends import_redis_smq_common25.EventEmitter {
|
|
|
3020
3107
|
}
|
|
3021
3108
|
run(cb) {
|
|
3022
3109
|
this.powerSwitch.goingUp();
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3110
|
+
import_redis_smq_common25.async.waterfall(
|
|
3111
|
+
[
|
|
3112
|
+
(cb2) => {
|
|
3113
|
+
if (typeof this.handler === "string") {
|
|
3114
|
+
if (![".js", ".cjs"].includes(import_path3.default.extname(this.handler))) {
|
|
3115
|
+
cb2(new ConsumerMessageHandlerFilenameExtensionError());
|
|
3116
|
+
} else
|
|
3117
|
+
(0, import_fs.stat)(this.handler, (err) => {
|
|
3118
|
+
if (err)
|
|
3119
|
+
cb2(new ConsumerMessageHandlerFileError());
|
|
3120
|
+
else
|
|
3121
|
+
cb2();
|
|
3122
|
+
});
|
|
3123
|
+
} else
|
|
3124
|
+
cb2();
|
|
3125
|
+
},
|
|
3126
|
+
(cb2) => this.dequeueMessage.run((err) => {
|
|
3127
|
+
if (err)
|
|
3128
|
+
cb2(err);
|
|
3129
|
+
else {
|
|
3130
|
+
this.powerSwitch.commit();
|
|
3131
|
+
this.emit("up");
|
|
3132
|
+
cb2();
|
|
3133
|
+
}
|
|
3134
|
+
})
|
|
3135
|
+
],
|
|
3136
|
+
(err) => {
|
|
3137
|
+
if (err)
|
|
3138
|
+
this.forceShutDown(() => cb(err));
|
|
3139
|
+
else
|
|
3140
|
+
cb();
|
|
3030
3141
|
}
|
|
3031
|
-
|
|
3142
|
+
);
|
|
3032
3143
|
}
|
|
3033
3144
|
shutdown(messageUnacknowledgedCause, cb) {
|
|
3034
3145
|
const goDown = () => {
|
|
3035
|
-
this.powerSwitch.goingDown();
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3146
|
+
const r = this.powerSwitch.goingDown();
|
|
3147
|
+
if (r) {
|
|
3148
|
+
import_redis_smq_common25.async.waterfall(
|
|
3149
|
+
[
|
|
3150
|
+
(cb2) => this.dequeueMessage.quit(cb2),
|
|
3151
|
+
(cb2) => this.consumeMessage.quit(cb2),
|
|
3152
|
+
(cb2) => this.cleanUp(messageUnacknowledgedCause, cb2),
|
|
3153
|
+
(cb2) => this.shutdownDequeueClient(cb2)
|
|
3154
|
+
],
|
|
3155
|
+
(err) => {
|
|
3156
|
+
if (err)
|
|
3157
|
+
cb(err);
|
|
3158
|
+
else {
|
|
3159
|
+
this.powerSwitch.commit();
|
|
3160
|
+
this.emit("down");
|
|
3161
|
+
cb();
|
|
3162
|
+
}
|
|
3049
3163
|
}
|
|
3050
|
-
|
|
3051
|
-
|
|
3164
|
+
);
|
|
3165
|
+
} else
|
|
3166
|
+
cb();
|
|
3052
3167
|
};
|
|
3053
3168
|
if (this.powerSwitch.isGoingUp())
|
|
3054
3169
|
this.once("up", goDown);
|
|
@@ -3147,7 +3262,12 @@ var MessageHandlerRunner = class {
|
|
|
3147
3262
|
client,
|
|
3148
3263
|
handlerParams
|
|
3149
3264
|
);
|
|
3150
|
-
handler.run(
|
|
3265
|
+
handler.run((err2) => {
|
|
3266
|
+
if (err2)
|
|
3267
|
+
this.removeMessageHandler(handlerParams.queue, () => cb(err2));
|
|
3268
|
+
else
|
|
3269
|
+
cb();
|
|
3270
|
+
});
|
|
3151
3271
|
}
|
|
3152
3272
|
});
|
|
3153
3273
|
}
|
|
@@ -4488,7 +4608,7 @@ var Message = class {
|
|
|
4488
4608
|
else {
|
|
4489
4609
|
cb(
|
|
4490
4610
|
null,
|
|
4491
|
-
reply.map((i) =>
|
|
4611
|
+
reply.map((i) => i.transfer())
|
|
4492
4612
|
);
|
|
4493
4613
|
}
|
|
4494
4614
|
});
|
|
@@ -4507,7 +4627,7 @@ var Message = class {
|
|
|
4507
4627
|
else if (!reply)
|
|
4508
4628
|
cb(new import_redis_smq_common36.CallbackEmptyReplyError());
|
|
4509
4629
|
else
|
|
4510
|
-
cb(null,
|
|
4630
|
+
cb(null, reply.transfer());
|
|
4511
4631
|
});
|
|
4512
4632
|
});
|
|
4513
4633
|
}
|
|
@@ -5727,6 +5847,10 @@ function disconnect(cb) {
|
|
|
5727
5847
|
ConsumerGroups,
|
|
5728
5848
|
ConsumerInvalidGroupIdError,
|
|
5729
5849
|
ConsumerMessageHandlerAlreadyExistsError,
|
|
5850
|
+
ConsumerMessageHandlerError,
|
|
5851
|
+
ConsumerMessageHandlerFileError,
|
|
5852
|
+
ConsumerMessageHandlerFilenameExtensionError,
|
|
5853
|
+
ConsumerMessageHandlerWorkerError,
|
|
5730
5854
|
EConsumeMessageDeadLetterCause,
|
|
5731
5855
|
EConsumeMessageUnacknowledgedCause,
|
|
5732
5856
|
EExchangeType,
|
|
@@ -5736,6 +5860,8 @@ function disconnect(cb) {
|
|
|
5736
5860
|
EQueueDeliveryModel,
|
|
5737
5861
|
EQueueProperty,
|
|
5738
5862
|
EQueueType,
|
|
5863
|
+
EWorkerThreadMessageCodeConsume,
|
|
5864
|
+
EWorkerThreadMessageCodeExit,
|
|
5739
5865
|
ExchangeDirect,
|
|
5740
5866
|
ExchangeError,
|
|
5741
5867
|
ExchangeFanOut,
|