redis-smq 7.1.0 → 7.1.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/CHANGELOG.md +13 -0
- package/README.md +42 -40
- package/dist/src/lib/exchange/fan-out-exchange-manager.js +33 -40
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 7.1.2 (2022-10-22)
|
|
4
|
+
|
|
5
|
+
* fix(FanOutExchangeManager): fix unbindQueue() transaction handling (dec63de)
|
|
6
|
+
* fix(FanOutExchangeManager): fix bindQueue() transaction handling (afbdde6)
|
|
7
|
+
* docs(queues): fix typos (08f29c0)
|
|
8
|
+
* docs(queues): add queues.md reference, clean up (3219eb8)
|
|
9
|
+
* docs: improve documentation, add missing links (c740e11)
|
|
10
|
+
|
|
11
|
+
## 7.1.1 (2022-10-11)
|
|
12
|
+
|
|
13
|
+
* docs(message-exchanges): update docs (19d7dd3)
|
|
14
|
+
* docs: update README (63b2fe6)
|
|
15
|
+
|
|
3
16
|
## 7.1.0 (2022-10-06)
|
|
4
17
|
|
|
5
18
|
* docs: update README.md (8734e49)
|
package/README.md
CHANGED
|
@@ -18,20 +18,20 @@ RedisSMQ is a Node.js library for queuing messages (aka jobs) and processing the
|
|
|
18
18
|
## Features
|
|
19
19
|
|
|
20
20
|
* **[High-performance message processing](/docs/performance.md)**.
|
|
21
|
-
* **[Multi-Queue Producers](#producer
|
|
22
|
-
* **[
|
|
23
|
-
* **[
|
|
21
|
+
* **[Multi-Queue Producers](#producer) & [Multi-Queue Consumers](#consumer)**: Offering flexible Producer/Consumer models, with focus on simplicity and without tons of features. This can make RedisSMQ an ideal message broker for your microservices.
|
|
22
|
+
* **[at-least-once/at-most-once Delivery](/docs/api/message.md#messageprototypesetretrythreshold)**: In case of failures, while delivering or processing a message, RedisSMQ can guaranty that the message will be not lost and redelivered again. When configured to do so, RedisSMQ can also ensure that the message is delivered at-most-once.
|
|
23
|
+
* **[Different Exchange Types](/docs/message-exchanges.md)**: RedisSMQ offers 3 types of exchanges: [Direct Exchange](/docs/message-exchanges.md#direct-exchange), [Topic Exchange](/docs/message-exchanges.md#topic-exchange), and [Fanout Exchange](/docs/message-exchanges.md#fanout-exchange) for publishing a message to one or multiple queues.
|
|
24
24
|
* **[Message Expiration](/docs/api/message.md#messageprototypesetttl)**: A message will not be delivered if it has been in a queue for longer than a given amount of time, called TTL (time-to-live).
|
|
25
25
|
* **[Message Consumption Timeout](/docs/api/message.md#messageprototypesetconsumetimeout)**: Timeout for consuming messages.
|
|
26
26
|
* **[Queue Rate Limiting](/docs/queue-rate-limiting.md)**: Allowing you to control the rate at which the messages are consumed from a given queue.
|
|
27
27
|
* **[Scheduling Messages](/docs/scheduling-messages.md)**: Messages can be configured to be delayed, delivered for N times with an optional period between deliveries, and to be scheduled using CRON expressions.
|
|
28
|
-
* **[Reliable Priority Queues](/docs/
|
|
28
|
+
* **[Reliable Priority Queues](/docs/queues.md)**: Supports priority messaging.
|
|
29
29
|
* **[Multiplexing](/docs/multiplexing.md)**: A feature which allows message handlers to use a single redis connection to dequeue and consume messages.
|
|
30
30
|
* **[HTTP API](https://github.com/weyoss/redis-smq-monitor)**: an HTTP interface is provided to interact with the MQ.
|
|
31
31
|
* **[Web UI](https://github.com/weyoss/redis-smq-monitor-client)**: RedisSMQ can be managed also from your web browser.
|
|
32
32
|
* **[Logging](https://github.com/weyoss/redis-smq-common/blob/master/docs/logs.md)**: RedisSMQ comes with a built-in JSON logger, but can also use your application logger.
|
|
33
33
|
* **[Configurable](/docs/configuration.md)**: Many options and features can be configured.
|
|
34
|
-
* **[
|
|
34
|
+
* **[Multiple Redis clients](/docs/configuration.md)**: Depending on your preferences, RedisSMQ can use either [node-redis v3](https://github.com/redis/node-redis/tree/v3.1.2), [node-redis v4](https://github.com/redis/node-redis), or [ioredis](https://github.com/luin/ioredis).
|
|
35
35
|
* **[Highly optimized](https://lgtm.com/projects/g/weyoss/redis-smq/context:javascript)**: Strongly-typed and implemented using pure callbacks, with small memory footprint and no memory leaks. See [Callback vs Promise vs Async/Await benchmarks](https://gist.github.com/weyoss/24f9ecbda175d943a48cb7ec38bde821).
|
|
36
36
|
|
|
37
37
|
|
|
@@ -47,22 +47,21 @@ RedisSMQ is a Node.js library for queuing messages (aka jobs) and processing the
|
|
|
47
47
|
2. [Installation](#installation)
|
|
48
48
|
3. [Configuration](#configuration)
|
|
49
49
|
4. [Usage](#usage)
|
|
50
|
-
1. Basics
|
|
51
|
-
1. [Message
|
|
52
|
-
2. [Producer
|
|
53
|
-
3. [Consumer
|
|
50
|
+
1. [Basics](#basics)
|
|
51
|
+
1. [Message](#message)
|
|
52
|
+
2. [Producer](#producer)
|
|
53
|
+
3. [Consumer](#consumer)
|
|
54
54
|
1. [Message Acknowledgement](#message-acknowledgement)
|
|
55
|
-
2. Advanced Topics
|
|
55
|
+
2. [Advanced Topics](#advanced-topics)
|
|
56
56
|
1. [Scheduling Messages](/docs/scheduling-messages.md)
|
|
57
|
-
2. [
|
|
58
|
-
3. [
|
|
59
|
-
4. [
|
|
60
|
-
5. [
|
|
61
|
-
6. [
|
|
62
|
-
7. [
|
|
63
|
-
8. [
|
|
64
|
-
9. [
|
|
65
|
-
10. [Logs](https://github.com/weyoss/redis-smq-common/blob/master/docs/logs.md)
|
|
57
|
+
2. [Message Exchanges](/docs/message-exchanges.md)
|
|
58
|
+
3. [Queue Rate Limiting](/docs/queue-rate-limiting.md)
|
|
59
|
+
4. [Multiplexing](/docs/multiplexing.md)
|
|
60
|
+
5. [Message Manager](/docs/api/message-manager.md)
|
|
61
|
+
6. [Queue Manager](/docs/api/queue-manager.md)
|
|
62
|
+
7. [HTTP API](https://github.com/weyoss/redis-smq-monitor)
|
|
63
|
+
8. [Web UI](https://github.com/weyoss/redis-smq-monitor-client)
|
|
64
|
+
9. [Logs](https://github.com/weyoss/redis-smq-common/blob/master/docs/logs.md)
|
|
66
65
|
5. [RedisSMQ Architecture](/docs/redis-smq-architecture.md)
|
|
67
66
|
6. [Performance](#performance)
|
|
68
67
|
7. [Contributing](#contributing)
|
|
@@ -72,9 +71,9 @@ RedisSMQ is a Node.js library for queuing messages (aka jobs) and processing the
|
|
|
72
71
|
|
|
73
72
|
**2022.10.06**
|
|
74
73
|
|
|
75
|
-
:rocket:
|
|
76
|
-
Also, the [Web UI](https://github.com/weyoss/redis-smq-monitor-client) has been reworked for better user experience and
|
|
77
|
-
|
|
74
|
+
:rocket: RedisSMQ v7.1 is out! This new release extends the message queue features by introducing [Message Exchanges](/docs/message-exchanges.md).
|
|
75
|
+
Also, the [Web UI](https://github.com/weyoss/redis-smq-monitor-client) has been reworked for better user experience and
|
|
76
|
+
to fully support message exchanges and other various routine operations.
|
|
78
77
|
|
|
79
78
|
## Installation
|
|
80
79
|
|
|
@@ -93,9 +92,15 @@ See [Configuration](/docs/configuration.md) for more details.
|
|
|
93
92
|
|
|
94
93
|
## Usage
|
|
95
94
|
|
|
96
|
-
|
|
95
|
+
### Basics
|
|
96
|
+
|
|
97
|
+
RedisSMQ provides 3 classes in order to work with the message queue: `Message`, `Producer`, and `Consumer`.
|
|
98
|
+
|
|
99
|
+
Producers and consumers exchange data using one or multiple queues that may be created using the [QueueManager](/docs/api/queue-manager.md).
|
|
100
|
+
|
|
101
|
+
A queue is responsible for holding messages which are produced by producers and are delivered to consumers.
|
|
97
102
|
|
|
98
|
-
|
|
103
|
+
RedisSMQ supports 2 types of queues: [LIFO Queues and Priority Queues](/docs/queues.md).
|
|
99
104
|
|
|
100
105
|
```javascript
|
|
101
106
|
const { QueueManager } = require('redis-smq');
|
|
@@ -103,15 +108,14 @@ const config = require('./config')
|
|
|
103
108
|
|
|
104
109
|
QueueManager.createInstance(config, (err, queueManager) => {
|
|
105
110
|
if (err) console.log(err);
|
|
111
|
+
// Creating a LIFO queue
|
|
106
112
|
else queueManager.queue.create('test_queue', false, (err) => console.log(err));
|
|
107
113
|
})
|
|
108
114
|
```
|
|
109
115
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
RedisSMQ provides 3 classes in order to work with the message queue: `Message`, `Producer`, and `Consumer`.
|
|
116
|
+
See [Queues](/docs/queues.md) for more details.
|
|
113
117
|
|
|
114
|
-
#### Message
|
|
118
|
+
#### Message
|
|
115
119
|
|
|
116
120
|
`Message` class is responsible for creating messages that may be published.
|
|
117
121
|
|
|
@@ -124,21 +128,21 @@ const { Message } = require('redis-smq');
|
|
|
124
128
|
const message = new Message();
|
|
125
129
|
message
|
|
126
130
|
.setBody({hello: 'world'})
|
|
127
|
-
.setTTL(3600000)
|
|
128
|
-
.
|
|
131
|
+
.setTTL(3600000)
|
|
132
|
+
.setRetryThreshold(5);
|
|
129
133
|
```
|
|
130
134
|
|
|
131
135
|
The `Message` class provides many methods for setting up different message parameters such as message body, message priority, message TTL, etc.
|
|
132
136
|
|
|
133
137
|
See [Message Reference](/docs/api/message.md) for more details.
|
|
134
138
|
|
|
135
|
-
#### Producer
|
|
139
|
+
#### Producer
|
|
136
140
|
|
|
137
|
-
A `Producer` instance allows
|
|
141
|
+
A `Producer` instance allows to publish a message to a queue.
|
|
138
142
|
|
|
139
|
-
You can use a single `Producer` instance to produce messages, including messages with priority, to multiple queues.
|
|
143
|
+
You can use a single `Producer` instance to produce messages, including messages with priority, to one or multiple queues.
|
|
140
144
|
|
|
141
|
-
Before publishing a message do not forget to set
|
|
145
|
+
Before publishing a message do not forget to set an exchange for the message using [setQueue()](/docs/api/message.md#messageprototypesetqueue), [setTopic()](/docs/api/message.md#messageprototypesettopic), or [setFanOut()](/docs/api/message.md#messageprototypesetfanout). Otherwise, an error will be returned. See [Message Exchanges](/docs/message-exchanges.md) for more details.
|
|
142
146
|
|
|
143
147
|
```javascript
|
|
144
148
|
'use strict';
|
|
@@ -150,8 +154,8 @@ producer.run((err) => {
|
|
|
150
154
|
const message = new Message();
|
|
151
155
|
message
|
|
152
156
|
.setBody({hello: 'world'})
|
|
153
|
-
.setTTL(3600000) // in millis
|
|
154
|
-
.setQueue('test_queue');
|
|
157
|
+
.setTTL(3600000) // message expiration (in millis)
|
|
158
|
+
.setQueue('test_queue'); // setting up a direct exchange
|
|
155
159
|
message.getId() // null
|
|
156
160
|
producer.produce(message, (err) => {
|
|
157
161
|
if (err) console.log(err);
|
|
@@ -167,11 +171,11 @@ Starting with v7.0.6, before producing messages you need first to run your produ
|
|
|
167
171
|
|
|
168
172
|
See [Producer Reference](/docs/api/producer.md) for more details.
|
|
169
173
|
|
|
170
|
-
#### Consumer
|
|
174
|
+
#### Consumer
|
|
171
175
|
|
|
172
176
|
A `Consumer` instance can be used to receive and consume messages from one or multiple queues.
|
|
173
177
|
|
|
174
|
-
To consume messages from a queue, the `Consumer` class provides the [consume()](/docs/api/consumer.md#consumerprototypeconsume) method which allows
|
|
178
|
+
To consume messages from a queue, the `Consumer` class provides the [consume()](/docs/api/consumer.md#consumerprototypeconsume) method which allows to register a `message handler`.
|
|
175
179
|
|
|
176
180
|
A `message handler` is a function that receives a delivered message from a given queue.
|
|
177
181
|
|
|
@@ -225,8 +229,6 @@ See [Consumer Reference](/docs/api/consumer.md) for more details.
|
|
|
225
229
|
|
|
226
230
|
* [Scheduling Messages](/docs/scheduling-messages.md)
|
|
227
231
|
|
|
228
|
-
* [Priority Queues](/docs/priority-queues.md)
|
|
229
|
-
|
|
230
232
|
* [Message Exchanges](/docs/message-exchanges.md)
|
|
231
233
|
|
|
232
234
|
* [Queue Rate Limiting](/docs/queue-rate-limiting.md)
|
|
@@ -40,33 +40,28 @@ class FanOutExchangeManager {
|
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
bindQueue(queue, exchange, cb) {
|
|
43
|
+
const exchangeParams = exchange.getBindingParams();
|
|
44
|
+
const queueParams = queue_1.Queue.getParams(this.config, queue);
|
|
45
|
+
const { keyQueues, keyQueueSettings } = redis_keys_1.redisKeys.getQueueKeys(queueParams);
|
|
46
|
+
const { keyExchanges, keyExchangeBindings } = redis_keys_1.redisKeys.getFanOutExchangeKeys(exchangeParams);
|
|
43
47
|
redis_smq_common_1.async.waterfall([
|
|
48
|
+
(cb) => this.redisClient.watch([keyQueues, keyQueueSettings, keyExchangeBindings], (err) => cb(err)),
|
|
44
49
|
(cb) => queue_1.Queue.getSettings(this.config, this.redisClient, queue, cb),
|
|
45
50
|
(queueSettings, cb) => {
|
|
46
|
-
const exchangeParams = exchange.getBindingParams();
|
|
47
51
|
const currentExchangeParams = queueSettings.exchange;
|
|
48
52
|
if (currentExchangeParams === exchangeParams)
|
|
49
53
|
cb();
|
|
50
54
|
else {
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
multi.sadd(keyExchangeBindings, queueParamsStr);
|
|
62
|
-
multi.hset(keyQueueSettings, types_1.EQueueSettingType.EXCHANGE, exchangeParams);
|
|
63
|
-
if (currentExchangeParams) {
|
|
64
|
-
const { keyExchangeBindings } = redis_keys_1.redisKeys.getFanOutExchangeKeys(currentExchangeParams);
|
|
65
|
-
multi.srem(keyExchangeBindings, queueParamsStr);
|
|
66
|
-
}
|
|
67
|
-
multi.exec((err) => cb(err));
|
|
68
|
-
}
|
|
69
|
-
});
|
|
55
|
+
const multi = this.redisClient.multi();
|
|
56
|
+
const queueParamsStr = JSON.stringify(queueParams);
|
|
57
|
+
multi.sadd(keyExchanges, exchangeParams);
|
|
58
|
+
multi.sadd(keyExchangeBindings, queueParamsStr);
|
|
59
|
+
multi.hset(keyQueueSettings, types_1.EQueueSettingType.EXCHANGE, exchangeParams);
|
|
60
|
+
if (currentExchangeParams) {
|
|
61
|
+
const { keyExchangeBindings } = redis_keys_1.redisKeys.getFanOutExchangeKeys(currentExchangeParams);
|
|
62
|
+
multi.srem(keyExchangeBindings, queueParamsStr);
|
|
63
|
+
}
|
|
64
|
+
multi.exec((err) => cb(err));
|
|
70
65
|
}
|
|
71
66
|
},
|
|
72
67
|
], (err) => {
|
|
@@ -77,28 +72,26 @@ class FanOutExchangeManager {
|
|
|
77
72
|
});
|
|
78
73
|
}
|
|
79
74
|
unbindQueue(queue, exchange, cb) {
|
|
75
|
+
const exchangeName = exchange.getBindingParams();
|
|
76
|
+
const queueParams = queue_1.Queue.getParams(this.config, queue);
|
|
77
|
+
const { keyQueues, keyQueueSettings } = redis_keys_1.redisKeys.getQueueKeys(queueParams);
|
|
78
|
+
const { keyExchangeBindings } = redis_keys_1.redisKeys.getFanOutExchangeKeys(exchangeName);
|
|
80
79
|
redis_smq_common_1.async.waterfall([
|
|
81
|
-
(cb) =>
|
|
82
|
-
(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (
|
|
80
|
+
(cb) => this.redisClient.watch([keyQueues, keyQueueSettings, keyExchangeBindings], (err) => cb(err)),
|
|
81
|
+
(cb) => queue_1.Queue.getSettings(this.config, this.redisClient, queue, (err, settings) => {
|
|
82
|
+
if (err)
|
|
83
|
+
cb(err);
|
|
84
|
+
else if ((settings === null || settings === void 0 ? void 0 : settings.exchange) !== exchangeName)
|
|
86
85
|
cb(new exchange_error_1.ExchangeError(`Queue ${queueParams.name}@${queueParams.ns} is not bound to [${exchangeName}] exchange.`));
|
|
87
|
-
else
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
multi.srem(keyExchangeBindings, queueParamsStr);
|
|
97
|
-
multi.hdel(keyQueueSettings, types_1.EQueueSettingType.EXCHANGE);
|
|
98
|
-
multi.exec((err) => cb(err));
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
}
|
|
86
|
+
else
|
|
87
|
+
cb();
|
|
88
|
+
}),
|
|
89
|
+
(cb) => {
|
|
90
|
+
const multi = this.redisClient.multi();
|
|
91
|
+
const queueParamsStr = JSON.stringify(queueParams);
|
|
92
|
+
multi.srem(keyExchangeBindings, queueParamsStr);
|
|
93
|
+
multi.hdel(keyQueueSettings, types_1.EQueueSettingType.EXCHANGE);
|
|
94
|
+
multi.exec((err) => cb(err));
|
|
102
95
|
},
|
|
103
96
|
], (err) => {
|
|
104
97
|
if (err)
|