redis-smq 8.0.0-rc.15 → 8.0.0-rc.16
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 +29 -0
- package/README.md +18 -15
- package/dist/index.cjs +210 -106
- package/dist/index.d.cts +189 -139
- package/dist/index.d.ts +189 -139
- package/dist/index.js +214 -114
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
## [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)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* allow running/sandboxing message handlers using worker threads ([53095bd](https://github.com/weyoss/redis-smq/commit/53095bd2689ccb2f701365bafb4ef8e550da82b3))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* export message handler errors ([26d2689](https://github.com/weyoss/redis-smq/commit/26d26890da139d88c46ce220e3dda3d9c8e03aee))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Documentation
|
|
17
|
+
|
|
18
|
+
* **ConsumeMessageWorker:** update docs and clean up ([140322e](https://github.com/weyoss/redis-smq/commit/140322e3520ee3db905ea977a159064f339aa7d2))
|
|
19
|
+
* fix broken links ([aad9010](https://github.com/weyoss/redis-smq/commit/aad9010e70ed332b154f4fbdcb8ac657a14fe6b9))
|
|
20
|
+
* update messages and queues documentation ([7c3d06e](https://github.com/weyoss/redis-smq/commit/7c3d06ed3765ffc14dfece4f725241aa4535e1e7))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Codebase Refactoring
|
|
24
|
+
|
|
25
|
+
* **ConsumeMessageWorker:** improve typings ([66c6ca9](https://github.com/weyoss/redis-smq/commit/66c6ca948677f76d496fe0b988bd195e1a7108a2))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Tests
|
|
29
|
+
|
|
30
|
+
* allow running/sandboxing message handlers using worker threads ([79e6886](https://github.com/weyoss/redis-smq/commit/79e688674ed11ec34ce2f74d5f15c8eefa129767))
|
|
31
|
+
|
|
3
32
|
## [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
33
|
|
|
5
34
|
|
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,8 @@ __export(redis_smq_exports, {
|
|
|
69
69
|
ConsumerGroups: () => ConsumerGroups,
|
|
70
70
|
ConsumerInvalidGroupIdError: () => ConsumerInvalidGroupIdError,
|
|
71
71
|
ConsumerMessageHandlerAlreadyExistsError: () => ConsumerMessageHandlerAlreadyExistsError,
|
|
72
|
+
ConsumerMessageHandlerError: () => ConsumerMessageHandlerError,
|
|
73
|
+
ConsumerMessageHandlerWorkerError: () => ConsumerMessageHandlerWorkerError,
|
|
72
74
|
EConsumeMessageDeadLetterCause: () => EConsumeMessageDeadLetterCause,
|
|
73
75
|
EConsumeMessageUnacknowledgedCause: () => EConsumeMessageUnacknowledgedCause,
|
|
74
76
|
EExchangeType: () => EExchangeType,
|
|
@@ -78,6 +80,8 @@ __export(redis_smq_exports, {
|
|
|
78
80
|
EQueueDeliveryModel: () => EQueueDeliveryModel,
|
|
79
81
|
EQueueProperty: () => EQueueProperty,
|
|
80
82
|
EQueueType: () => EQueueType,
|
|
83
|
+
EWorkerThreadMessageCodeConsume: () => EWorkerThreadMessageCodeConsume,
|
|
84
|
+
EWorkerThreadMessageCodeExit: () => EWorkerThreadMessageCodeExit,
|
|
81
85
|
ExchangeDirect: () => ExchangeDirect,
|
|
82
86
|
ExchangeError: () => ExchangeError,
|
|
83
87
|
ExchangeFanOut: () => ExchangeFanOut,
|
|
@@ -437,6 +441,22 @@ var EConsumeMessageUnacknowledgedCause = /* @__PURE__ */ ((EConsumeMessageUnackn
|
|
|
437
441
|
return EConsumeMessageUnacknowledgedCause3;
|
|
438
442
|
})(EConsumeMessageUnacknowledgedCause || {});
|
|
439
443
|
|
|
444
|
+
// types/consumer/consume-message-worker.ts
|
|
445
|
+
var EWorkerThreadMessageCodeExit = /* @__PURE__ */ ((EWorkerThreadMessageCodeExit2) => {
|
|
446
|
+
EWorkerThreadMessageCodeExit2[EWorkerThreadMessageCodeExit2["WORKER_DATA_REQUIRED"] = 100] = "WORKER_DATA_REQUIRED";
|
|
447
|
+
EWorkerThreadMessageCodeExit2[EWorkerThreadMessageCodeExit2["INVALID_HANDLER_TYPE"] = 101] = "INVALID_HANDLER_TYPE";
|
|
448
|
+
EWorkerThreadMessageCodeExit2[EWorkerThreadMessageCodeExit2["HANDLER_IMPORT_ERROR"] = 102] = "HANDLER_IMPORT_ERROR";
|
|
449
|
+
EWorkerThreadMessageCodeExit2[EWorkerThreadMessageCodeExit2["UNCAUGHT_EXCEPTION"] = 103] = "UNCAUGHT_EXCEPTION";
|
|
450
|
+
EWorkerThreadMessageCodeExit2[EWorkerThreadMessageCodeExit2["TERMINATED"] = 104] = "TERMINATED";
|
|
451
|
+
return EWorkerThreadMessageCodeExit2;
|
|
452
|
+
})(EWorkerThreadMessageCodeExit || {});
|
|
453
|
+
var EWorkerThreadMessageCodeConsume = /* @__PURE__ */ ((EWorkerThreadMessageCodeConsume2) => {
|
|
454
|
+
EWorkerThreadMessageCodeConsume2[EWorkerThreadMessageCodeConsume2["OK"] = 200] = "OK";
|
|
455
|
+
EWorkerThreadMessageCodeConsume2[EWorkerThreadMessageCodeConsume2["MESSAGE_PROCESSING_ERROR"] = 201] = "MESSAGE_PROCESSING_ERROR";
|
|
456
|
+
EWorkerThreadMessageCodeConsume2[EWorkerThreadMessageCodeConsume2["MESSAGE_PROCESSING_CAUGHT_ERROR"] = 202] = "MESSAGE_PROCESSING_CAUGHT_ERROR";
|
|
457
|
+
return EWorkerThreadMessageCodeConsume2;
|
|
458
|
+
})(EWorkerThreadMessageCodeConsume || {});
|
|
459
|
+
|
|
440
460
|
// types/exchange/common.ts
|
|
441
461
|
var EExchangeType = /* @__PURE__ */ ((EExchangeType2) => {
|
|
442
462
|
EExchangeType2[EExchangeType2["DIRECT"] = 0] = "DIRECT";
|
|
@@ -674,6 +694,23 @@ var MessageDeleteError = class extends MessageError {
|
|
|
674
694
|
}
|
|
675
695
|
};
|
|
676
696
|
|
|
697
|
+
// src/lib/consumer/message-handler/errors/consumer-message-handler.error.ts
|
|
698
|
+
var ConsumerMessageHandlerError = class extends ConsumerError {
|
|
699
|
+
constructor(msg) {
|
|
700
|
+
super(msg);
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
// src/lib/consumer/message-handler/errors/consumer-message-handler-worker.error.ts
|
|
705
|
+
var ConsumerMessageHandlerWorkerError = class extends ConsumerMessageHandlerError {
|
|
706
|
+
constructor(msg) {
|
|
707
|
+
const { code, error } = msg;
|
|
708
|
+
super(
|
|
709
|
+
`Error code: ${code}.${error ? `Message: ${error.name}: ${error.message}` : ""}`
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
};
|
|
713
|
+
|
|
677
714
|
// src/lib/consumer/consumer-heartbeat.ts
|
|
678
715
|
var os = __toESM(require("os"), 1);
|
|
679
716
|
var import_redis_smq_common10 = require("redis-smq-common");
|
|
@@ -981,6 +1018,8 @@ var Base = class extends import_redis_smq_common11.EventEmitter {
|
|
|
981
1018
|
};
|
|
982
1019
|
|
|
983
1020
|
// src/lib/consumer/message-handler/message-handler.ts
|
|
1021
|
+
var import_fs = require("fs");
|
|
1022
|
+
var import_path3 = __toESM(require("path"), 1);
|
|
984
1023
|
var import_uuid4 = require("uuid");
|
|
985
1024
|
|
|
986
1025
|
// src/lib/consumer/message-handler/processing-queue.ts
|
|
@@ -1419,6 +1458,13 @@ var MessageEnvelope = class {
|
|
|
1419
1458
|
consumerGroupId: this.getConsumerGroupId()
|
|
1420
1459
|
};
|
|
1421
1460
|
}
|
|
1461
|
+
transfer() {
|
|
1462
|
+
return __spreadProps(__spreadValues({}, this.toJSON()), {
|
|
1463
|
+
id: this.getId(),
|
|
1464
|
+
messageState: this.getMessageState().toJSON(),
|
|
1465
|
+
status: this.getStatus()
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1422
1468
|
hasRetryThresholdExceeded() {
|
|
1423
1469
|
const threshold = this.producibleMessage.getRetryThreshold();
|
|
1424
1470
|
return this.messageState.getAttempts() + 1 >= threshold;
|
|
@@ -2679,87 +2725,76 @@ var DequeueMessage = class {
|
|
|
2679
2725
|
// src/lib/consumer/message-handler/consume-message.ts
|
|
2680
2726
|
var import_redis_smq_common24 = require("redis-smq-common");
|
|
2681
2727
|
|
|
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();
|
|
2728
|
+
// src/lib/consumer/message-handler/consume-message-worker.ts
|
|
2729
|
+
var import_path2 = __toESM(require("path"), 1);
|
|
2730
|
+
var import_worker_threads = require("worker_threads");
|
|
2731
|
+
var ConsumeMessageWorker = class {
|
|
2732
|
+
constructor(messageHandlerFilename) {
|
|
2733
|
+
this.messageHandlerThread = null;
|
|
2734
|
+
this.messageHandlerFilename = messageHandlerFilename;
|
|
2735
|
+
}
|
|
2736
|
+
getMessageHandlerThread() {
|
|
2737
|
+
if (!this.messageHandlerThread) {
|
|
2738
|
+
this.messageHandlerThread = new import_worker_threads.Worker(
|
|
2739
|
+
import_path2.default.resolve(__dirname, "./consume-message-worker-thread.js"),
|
|
2740
|
+
{
|
|
2741
|
+
workerData: this.messageHandlerFilename
|
|
2742
|
+
}
|
|
2743
|
+
);
|
|
2744
|
+
this.messageHandlerThread.on("messageerror", (err) => {
|
|
2745
|
+
console.error(err);
|
|
2746
|
+
});
|
|
2747
|
+
this.messageHandlerThread.on("error", (err) => {
|
|
2748
|
+
console.error(err);
|
|
2749
|
+
});
|
|
2750
|
+
this.messageHandlerThread.on("exit", () => {
|
|
2751
|
+
this.messageHandlerThread = null;
|
|
2752
|
+
});
|
|
2756
2753
|
}
|
|
2757
|
-
|
|
2758
|
-
}
|
|
2754
|
+
return this.messageHandlerThread;
|
|
2755
|
+
}
|
|
2756
|
+
consume(message, cb) {
|
|
2757
|
+
const worker = this.getMessageHandlerThread();
|
|
2758
|
+
const cleanUp = () => {
|
|
2759
|
+
worker.removeListener("message", onMessage).removeListener("exit", onExit);
|
|
2760
|
+
};
|
|
2761
|
+
const onMessage = (msg) => {
|
|
2762
|
+
cleanUp();
|
|
2763
|
+
if (msg.code !== 200 /* OK */) {
|
|
2764
|
+
console.error(`ConsumerMessageHandlerWorkerError`, msg);
|
|
2765
|
+
cb(new ConsumerMessageHandlerWorkerError(msg));
|
|
2766
|
+
} else
|
|
2767
|
+
cb();
|
|
2768
|
+
};
|
|
2769
|
+
const onExit = () => {
|
|
2770
|
+
cleanUp();
|
|
2771
|
+
const msg = {
|
|
2772
|
+
code: 104 /* TERMINATED */,
|
|
2773
|
+
error: null
|
|
2774
|
+
};
|
|
2775
|
+
console.error("ConsumerMessageHandlerWorkerError", msg);
|
|
2776
|
+
cb(new ConsumerMessageHandlerWorkerError(msg));
|
|
2777
|
+
};
|
|
2778
|
+
worker.once("message", onMessage);
|
|
2779
|
+
worker.once("exit", onExit);
|
|
2780
|
+
worker.postMessage(message);
|
|
2781
|
+
}
|
|
2782
|
+
quit(cb) {
|
|
2783
|
+
const callback = () => {
|
|
2784
|
+
this.messageHandlerThread = null;
|
|
2785
|
+
cb();
|
|
2786
|
+
};
|
|
2787
|
+
if (this.messageHandlerThread) {
|
|
2788
|
+
this.messageHandlerThread.terminate().then(callback).catch(callback);
|
|
2789
|
+
} else
|
|
2790
|
+
cb();
|
|
2791
|
+
}
|
|
2792
|
+
};
|
|
2759
2793
|
|
|
2760
2794
|
// src/lib/consumer/message-handler/consume-message.ts
|
|
2761
2795
|
var ConsumeMessage = class {
|
|
2762
2796
|
constructor(messageHandler, redisClient2, logger3) {
|
|
2797
|
+
this.consumeMessageWorker = null;
|
|
2763
2798
|
this.redisClient = redisClient2;
|
|
2764
2799
|
this.messageHandler = messageHandler;
|
|
2765
2800
|
this.queue = messageHandler.getQueue();
|
|
@@ -2843,6 +2878,20 @@ var ConsumeMessage = class {
|
|
|
2843
2878
|
}
|
|
2844
2879
|
);
|
|
2845
2880
|
}
|
|
2881
|
+
getConsumeMessageWorker(messageHandlerFilename) {
|
|
2882
|
+
if (!this.consumeMessageWorker) {
|
|
2883
|
+
this.consumeMessageWorker = new ConsumeMessageWorker(
|
|
2884
|
+
messageHandlerFilename
|
|
2885
|
+
);
|
|
2886
|
+
}
|
|
2887
|
+
return this.consumeMessageWorker;
|
|
2888
|
+
}
|
|
2889
|
+
invokeMessageHandler(messageHandler, msg, cb) {
|
|
2890
|
+
if (typeof messageHandler === "string") {
|
|
2891
|
+
this.getConsumeMessageWorker(messageHandler).consume(msg, cb);
|
|
2892
|
+
} else
|
|
2893
|
+
messageHandler(msg, cb);
|
|
2894
|
+
}
|
|
2846
2895
|
consumeMessage(msg) {
|
|
2847
2896
|
let isTimeout = false;
|
|
2848
2897
|
let timer = null;
|
|
@@ -2884,8 +2933,9 @@ var ConsumeMessage = class {
|
|
|
2884
2933
|
}
|
|
2885
2934
|
}
|
|
2886
2935
|
};
|
|
2887
|
-
this.
|
|
2888
|
-
|
|
2936
|
+
this.invokeMessageHandler(
|
|
2937
|
+
this.messageHandler.getHandler(),
|
|
2938
|
+
msg.transfer(),
|
|
2889
2939
|
onConsumed
|
|
2890
2940
|
);
|
|
2891
2941
|
} catch (error) {
|
|
@@ -2905,6 +2955,12 @@ var ConsumeMessage = class {
|
|
|
2905
2955
|
} else
|
|
2906
2956
|
this.consumeMessage(message);
|
|
2907
2957
|
}
|
|
2958
|
+
quit(cb) {
|
|
2959
|
+
if (this.consumeMessageWorker) {
|
|
2960
|
+
this.consumeMessageWorker.quit(cb);
|
|
2961
|
+
} else
|
|
2962
|
+
cb();
|
|
2963
|
+
}
|
|
2908
2964
|
};
|
|
2909
2965
|
|
|
2910
2966
|
// src/lib/consumer/message-handler/message-handler.ts
|
|
@@ -2920,7 +2976,7 @@ var MessageHandler = class extends import_redis_smq_common25.EventEmitter {
|
|
|
2920
2976
|
this.dequeueRedisClient = dequeueRedisClient;
|
|
2921
2977
|
this.sharedRedisClient = sharedRedisClient;
|
|
2922
2978
|
this.handler = messageHandler;
|
|
2923
|
-
this.powerSwitch = new import_redis_smq_common25.PowerSwitch();
|
|
2979
|
+
this.powerSwitch = new import_redis_smq_common25.PowerSwitch(false);
|
|
2924
2980
|
this.logger = logger3;
|
|
2925
2981
|
this.dequeueMessage = new DequeueMessage(this, dequeueRedisClient);
|
|
2926
2982
|
this.consumeMessage = new ConsumeMessage(this, dequeueRedisClient, logger3);
|
|
@@ -3010,6 +3066,17 @@ var MessageHandler = class extends import_redis_smq_common25.EventEmitter {
|
|
|
3010
3066
|
shutdownDequeueClient(cb) {
|
|
3011
3067
|
this.dequeueRedisClient.halt(cb);
|
|
3012
3068
|
}
|
|
3069
|
+
forceShutDown(cb) {
|
|
3070
|
+
this.powerSwitch.rollback();
|
|
3071
|
+
import_redis_smq_common25.async.waterfall(
|
|
3072
|
+
[
|
|
3073
|
+
(cb2) => this.dequeueMessage.quit(cb2),
|
|
3074
|
+
(cb2) => this.consumeMessage.quit(cb2),
|
|
3075
|
+
(cb2) => this.shutdownDequeueClient(cb2)
|
|
3076
|
+
],
|
|
3077
|
+
cb
|
|
3078
|
+
);
|
|
3079
|
+
}
|
|
3013
3080
|
handleError(err) {
|
|
3014
3081
|
if (this.powerSwitch.isRunning() || this.powerSwitch.isGoingUp()) {
|
|
3015
3082
|
this.emit("error", err);
|
|
@@ -3020,35 +3087,63 @@ var MessageHandler = class extends import_redis_smq_common25.EventEmitter {
|
|
|
3020
3087
|
}
|
|
3021
3088
|
run(cb) {
|
|
3022
3089
|
this.powerSwitch.goingUp();
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3090
|
+
import_redis_smq_common25.async.waterfall(
|
|
3091
|
+
[
|
|
3092
|
+
(cb2) => {
|
|
3093
|
+
if (typeof this.handler === "string") {
|
|
3094
|
+
if (![".js", ".cjs"].includes(import_path3.default.extname(this.handler))) {
|
|
3095
|
+
cb2(new ConsumerMessageHandlerError("Invalid file extension"));
|
|
3096
|
+
} else
|
|
3097
|
+
(0, import_fs.stat)(this.handler, (err) => {
|
|
3098
|
+
if (err)
|
|
3099
|
+
cb2(new ConsumerMessageHandlerError(err.message));
|
|
3100
|
+
else
|
|
3101
|
+
cb2();
|
|
3102
|
+
});
|
|
3103
|
+
} else
|
|
3104
|
+
cb2();
|
|
3105
|
+
},
|
|
3106
|
+
(cb2) => this.dequeueMessage.run((err) => {
|
|
3107
|
+
if (err)
|
|
3108
|
+
cb2(err);
|
|
3109
|
+
else {
|
|
3110
|
+
this.powerSwitch.commit();
|
|
3111
|
+
this.emit("up");
|
|
3112
|
+
cb2();
|
|
3113
|
+
}
|
|
3114
|
+
})
|
|
3115
|
+
],
|
|
3116
|
+
(err) => {
|
|
3117
|
+
if (err)
|
|
3118
|
+
this.forceShutDown(() => cb(err));
|
|
3119
|
+
else
|
|
3120
|
+
cb();
|
|
3030
3121
|
}
|
|
3031
|
-
|
|
3122
|
+
);
|
|
3032
3123
|
}
|
|
3033
3124
|
shutdown(messageUnacknowledgedCause, cb) {
|
|
3034
3125
|
const goDown = () => {
|
|
3035
|
-
this.powerSwitch.goingDown();
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3126
|
+
const r = this.powerSwitch.goingDown();
|
|
3127
|
+
if (r) {
|
|
3128
|
+
import_redis_smq_common25.async.waterfall(
|
|
3129
|
+
[
|
|
3130
|
+
(cb2) => this.dequeueMessage.quit(cb2),
|
|
3131
|
+
(cb2) => this.consumeMessage.quit(cb2),
|
|
3132
|
+
(cb2) => this.cleanUp(messageUnacknowledgedCause, cb2),
|
|
3133
|
+
(cb2) => this.shutdownDequeueClient(cb2)
|
|
3134
|
+
],
|
|
3135
|
+
(err) => {
|
|
3136
|
+
if (err)
|
|
3137
|
+
cb(err);
|
|
3138
|
+
else {
|
|
3139
|
+
this.powerSwitch.commit();
|
|
3140
|
+
this.emit("down");
|
|
3141
|
+
cb();
|
|
3142
|
+
}
|
|
3049
3143
|
}
|
|
3050
|
-
|
|
3051
|
-
|
|
3144
|
+
);
|
|
3145
|
+
} else
|
|
3146
|
+
cb();
|
|
3052
3147
|
};
|
|
3053
3148
|
if (this.powerSwitch.isGoingUp())
|
|
3054
3149
|
this.once("up", goDown);
|
|
@@ -3147,7 +3242,12 @@ var MessageHandlerRunner = class {
|
|
|
3147
3242
|
client,
|
|
3148
3243
|
handlerParams
|
|
3149
3244
|
);
|
|
3150
|
-
handler.run(
|
|
3245
|
+
handler.run((err2) => {
|
|
3246
|
+
if (err2)
|
|
3247
|
+
this.removeMessageHandler(handlerParams.queue, () => cb(err2));
|
|
3248
|
+
else
|
|
3249
|
+
cb();
|
|
3250
|
+
});
|
|
3151
3251
|
}
|
|
3152
3252
|
});
|
|
3153
3253
|
}
|
|
@@ -4488,7 +4588,7 @@ var Message = class {
|
|
|
4488
4588
|
else {
|
|
4489
4589
|
cb(
|
|
4490
4590
|
null,
|
|
4491
|
-
reply.map((i) =>
|
|
4591
|
+
reply.map((i) => i.transfer())
|
|
4492
4592
|
);
|
|
4493
4593
|
}
|
|
4494
4594
|
});
|
|
@@ -4507,7 +4607,7 @@ var Message = class {
|
|
|
4507
4607
|
else if (!reply)
|
|
4508
4608
|
cb(new import_redis_smq_common36.CallbackEmptyReplyError());
|
|
4509
4609
|
else
|
|
4510
|
-
cb(null,
|
|
4610
|
+
cb(null, reply.transfer());
|
|
4511
4611
|
});
|
|
4512
4612
|
});
|
|
4513
4613
|
}
|
|
@@ -5727,6 +5827,8 @@ function disconnect(cb) {
|
|
|
5727
5827
|
ConsumerGroups,
|
|
5728
5828
|
ConsumerInvalidGroupIdError,
|
|
5729
5829
|
ConsumerMessageHandlerAlreadyExistsError,
|
|
5830
|
+
ConsumerMessageHandlerError,
|
|
5831
|
+
ConsumerMessageHandlerWorkerError,
|
|
5730
5832
|
EConsumeMessageDeadLetterCause,
|
|
5731
5833
|
EConsumeMessageUnacknowledgedCause,
|
|
5732
5834
|
EExchangeType,
|
|
@@ -5736,6 +5838,8 @@ function disconnect(cb) {
|
|
|
5736
5838
|
EQueueDeliveryModel,
|
|
5737
5839
|
EQueueProperty,
|
|
5738
5840
|
EQueueType,
|
|
5841
|
+
EWorkerThreadMessageCodeConsume,
|
|
5842
|
+
EWorkerThreadMessageCodeExit,
|
|
5739
5843
|
ExchangeDirect,
|
|
5740
5844
|
ExchangeError,
|
|
5741
5845
|
ExchangeFanOut,
|