redis-smq 3.0.3 → 3.2.0
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 +26 -5
- package/README.md +89 -24
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/src/consumer.d.ts +15 -17
- package/dist/src/consumer.js +118 -96
- package/dist/src/consumer.js.map +1 -1
- package/dist/src/events.d.ts +11 -14
- package/dist/src/events.js +11 -14
- package/dist/src/events.js.map +1 -1
- package/dist/src/gc-message-collector.d.ts +10 -7
- package/dist/src/gc-message-collector.js +20 -13
- package/dist/src/gc-message-collector.js.map +1 -1
- package/dist/src/gc.d.ts +18 -17
- package/dist/src/gc.js +149 -134
- package/dist/src/gc.js.map +1 -1
- package/dist/src/heartbeat-monitor.js +20 -18
- package/dist/src/heartbeat-monitor.js.map +1 -1
- package/dist/src/heartbeat.d.ts +40 -13
- package/dist/src/heartbeat.js +170 -181
- package/dist/src/heartbeat.js.map +1 -1
- package/dist/src/instance.d.ts +37 -22
- package/dist/src/instance.js +62 -112
- package/dist/src/instance.js.map +1 -1
- package/dist/src/lock-manager.d.ts +5 -7
- package/dist/src/lock-manager.js +7 -16
- package/dist/src/lock-manager.js.map +1 -1
- package/dist/src/logger.d.ts +1 -1
- package/dist/src/logger.js +7 -3
- package/dist/src/logger.js.map +1 -1
- package/dist/src/message.js.map +1 -1
- package/dist/src/monitor-server/controllers/scheduler/actions/delete-scheduled-message/delete-scheduled-message-request.DTO.d.ts +4 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/delete-scheduled-message/delete-scheduled-message-request.DTO.js +25 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/delete-scheduled-message/delete-scheduled-message-request.DTO.js.map +1 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/delete-scheduled-message/delete-scheduled-message-response.DTO.d.ts +4 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/delete-scheduled-message/delete-scheduled-message-response.DTO.js +26 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/delete-scheduled-message/delete-scheduled-message-response.DTO.js.map +1 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/delete-scheduled-message/delete-scheduled-message.handler.d.ts +5 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/delete-scheduled-message/delete-scheduled-message.handler.js +20 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/delete-scheduled-message/delete-scheduled-message.handler.js.map +1 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/get-scheduled-messages/get-scheduled-messages-request.DTO.d.ts +5 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/get-scheduled-messages/get-scheduled-messages-request.DTO.js +34 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/get-scheduled-messages/get-scheduled-messages-request.DTO.js.map +1 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/get-scheduled-messages/get-scheduled-messages-response.DTO.d.ts +28 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/get-scheduled-messages/get-scheduled-messages-response.DTO.js +128 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/get-scheduled-messages/get-scheduled-messages-response.DTO.js.map +1 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/get-scheduled-messages/get-scheduled-messages.handler.d.ts +6 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/get-scheduled-messages/get-scheduled-messages.handler.js +20 -0
- package/dist/src/monitor-server/controllers/scheduler/actions/get-scheduled-messages/get-scheduled-messages.handler.js.map +1 -0
- package/dist/src/monitor-server/controllers/scheduler/index.d.ts +25 -0
- package/dist/src/monitor-server/controllers/scheduler/index.js +32 -0
- package/dist/src/monitor-server/controllers/scheduler/index.js.map +1 -0
- package/dist/src/monitor-server/index.d.ts +9 -0
- package/dist/src/monitor-server/index.js +120 -0
- package/dist/src/monitor-server/index.js.map +1 -0
- package/dist/src/monitor-server/lib/routing.d.ts +29 -0
- package/dist/src/monitor-server/lib/routing.js +61 -0
- package/dist/src/monitor-server/lib/routing.js.map +1 -0
- package/dist/src/monitor-server/middlewares/error-handler.d.ts +2 -0
- package/dist/src/monitor-server/middlewares/error-handler.js +42 -0
- package/dist/src/monitor-server/middlewares/error-handler.js.map +1 -0
- package/dist/src/monitor-server/middlewares/request-validator.d.ts +4 -0
- package/dist/src/monitor-server/middlewares/request-validator.js +23 -0
- package/dist/src/monitor-server/middlewares/request-validator.js.map +1 -0
- package/dist/src/monitor-server/middlewares/response-validator.d.ts +3 -0
- package/dist/src/monitor-server/middlewares/response-validator.js +25 -0
- package/dist/src/monitor-server/middlewares/response-validator.js.map +1 -0
- package/dist/src/monitor-server/services/index.d.ts +5 -0
- package/dist/src/monitor-server/services/index.js +18 -0
- package/dist/src/monitor-server/services/index.js.map +1 -0
- package/dist/src/monitor-server/services/scheduler.service.d.ts +10 -0
- package/dist/src/monitor-server/services/scheduler.service.js +50 -0
- package/dist/src/monitor-server/services/scheduler.service.js.map +1 -0
- package/dist/src/{stats-aggregator.d.ts → monitor-server/threads/stats-aggregator.thread.d.ts} +0 -0
- package/dist/src/{stats-aggregator.js → monitor-server/threads/stats-aggregator.thread.js} +61 -68
- package/dist/src/monitor-server/threads/stats-aggregator.thread.js.map +1 -0
- package/dist/src/monitor-server/types/common.d.ts +39 -0
- package/dist/src/monitor-server/types/common.js +3 -0
- package/dist/src/monitor-server/types/common.js.map +1 -0
- package/dist/src/monitor-server/utils/thread-runner.d.ts +3 -0
- package/dist/src/monitor-server/utils/thread-runner.js +57 -0
- package/dist/src/monitor-server/utils/thread-runner.js.map +1 -0
- package/dist/src/monitor-server/utils/validate-dto.d.ts +2 -0
- package/dist/src/monitor-server/utils/validate-dto.js +31 -0
- package/dist/src/monitor-server/utils/validate-dto.js.map +1 -0
- package/dist/src/producer.d.ts +3 -4
- package/dist/src/producer.js +24 -23
- package/dist/src/producer.js.map +1 -1
- package/dist/src/queue-helpers.d.ts +10 -0
- package/dist/src/queue-helpers.js +45 -0
- package/dist/src/queue-helpers.js.map +1 -0
- package/dist/src/redis-client.d.ts +25 -21
- package/dist/src/redis-client.js +39 -18
- package/dist/src/redis-client.js.map +1 -1
- package/dist/src/redis-keys.d.ts +91 -0
- package/dist/src/redis-keys.js +156 -0
- package/dist/src/redis-keys.js.map +1 -0
- package/dist/src/scheduler-runner.d.ts +29 -0
- package/dist/src/scheduler-runner.js +111 -0
- package/dist/src/scheduler-runner.js.map +1 -0
- package/dist/src/scheduler.d.ts +15 -29
- package/dist/src/scheduler.js +149 -149
- package/dist/src/scheduler.js.map +1 -1
- package/dist/src/stats.d.ts +5 -9
- package/dist/src/stats.js +33 -45
- package/dist/src/stats.js.map +1 -1
- package/dist/src/ticker.d.ts +4 -3
- package/dist/src/ticker.js +29 -22
- package/dist/src/ticker.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +19 -4
- package/dist/types/index.js.map +1 -1
- package/docs/api/consumer.md +1 -1
- package/docs/api/scheduler.md +135 -0
- package/package.json +37 -16
- package/dist/src/redis-keys/consumer-redis-keys.d.ts +0 -57
- package/dist/src/redis-keys/consumer-redis-keys.js +0 -78
- package/dist/src/redis-keys/consumer-redis-keys.js.map +0 -1
- package/dist/src/redis-keys/mq-redis-keys.d.ts +0 -30
- package/dist/src/redis-keys/mq-redis-keys.js +0 -95
- package/dist/src/redis-keys/mq-redis-keys.js.map +0 -1
- package/dist/src/redis-keys/producer-redis-keys.d.ts +0 -25
- package/dist/src/redis-keys/producer-redis-keys.js +0 -36
- package/dist/src/redis-keys/producer-redis-keys.js.map +0 -1
- package/dist/src/stats-aggregator.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
-
## 3.0
|
|
3
|
+
## 3.2.0 (2021-10-01)
|
|
4
|
+
|
|
5
|
+
- Run tests in Node.js v12, v14, and v16
|
|
6
|
+
- Run tests in Redis v2.6.17, v3, v4, v5, and v6
|
|
7
|
+
- Made redis-smq-monitor server an integral part of redis-smq
|
|
8
|
+
- Implemented Scheduler HTTP API endpoints
|
|
9
|
+
- Various fixes and improvements
|
|
10
|
+
|
|
11
|
+
## 3.1.1 (2021-09-16)
|
|
12
|
+
|
|
13
|
+
* Added Github CI
|
|
14
|
+
|
|
15
|
+
## 3.1.0 (2021-09-15)
|
|
4
16
|
|
|
5
|
-
*
|
|
17
|
+
* Added Scheduler API docs.
|
|
18
|
+
* Added new methods to fetch and delete scheduled messages.
|
|
19
|
+
|
|
20
|
+
## 3.0.4 (2021-09-08)
|
|
21
|
+
|
|
22
|
+
* Updated examples.
|
|
23
|
+
|
|
24
|
+
## 3.0.3 (2021-09-08)
|
|
6
25
|
|
|
26
|
+
* Fixed .npmignore.
|
|
7
27
|
|
|
8
28
|
## 3.0.2 (2021-09-08)
|
|
9
29
|
|
|
@@ -15,10 +35,11 @@
|
|
|
15
35
|
|
|
16
36
|
## 3.0.0 (2021-09-08)
|
|
17
37
|
|
|
18
|
-
* A major release v3
|
|
38
|
+
* A major release v3 is out.
|
|
39
|
+
* Starting from this release, only active LTS and maintenance LTS Node.js releases are supported.
|
|
19
40
|
* Upgrading your installation to the newest version should be straightforward as most APIs are compatible with some exceptions.
|
|
20
|
-
* Project codebase has been migrated to TypeScript to make use of strong typings.
|
|
21
|
-
* JavaScript's users are always first class citizens
|
|
41
|
+
* Project codebase has been migrated to TypeScript to make use of strong typings.
|
|
42
|
+
* JavaScript's users are always first class citizens.
|
|
22
43
|
* Fixed a compatibility issue between ioredis and redis when calling multi.exec().
|
|
23
44
|
* Fixed typing inconsistencies (ConfigRedisDriver and RedisDriver types) between redis-smq and redis-smq-monitor.
|
|
24
45
|
* Improved scheduler mechanics, refactored GC, and updated tests.
|
package/README.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# RedisSMQ - Yet another simple Redis message queue
|
|
2
2
|
|
|
3
|
+
[](https://github.com/weyoss/redis-smq/actions/workflows/tests.yml)
|
|
4
|
+
[](https://coveralls.io/r/weyoss/redis-smq?branch=master)
|
|
5
|
+
[]((https://david-dm.org/weyoss/redis-smq))
|
|
6
|
+
[](https://npmjs.org/package/redis-smq)
|
|
7
|
+
[](https://npmjs.org/package/redis-smq)
|
|
8
|
+
[](https://lgtm.com/projects/g/weyoss/redis-smq/context:javascript)
|
|
9
|
+
|
|
3
10
|
A simple high-performance Redis message queue for Node.js.
|
|
4
11
|
|
|
5
12
|
For more details about RedisSMQ design see [https://medium.com/@weyoss/building-a-simple-message-queue-using-redis-server-and-node-js-964eda240a2a](https://medium.com/@weyoss/building-a-simple-message-queue-using-redis-server-and-node-js-964eda240a2a)
|
|
@@ -35,6 +42,7 @@ For more details about RedisSMQ design see [https://medium.com/@weyoss/building-
|
|
|
35
42
|
1. [Message Class](#message-class)
|
|
36
43
|
2. [Producer Class](#producer-class)
|
|
37
44
|
3. [Consumer Class](#consumer-class)
|
|
45
|
+
4. [Message Scheduler](#message-scheduler)
|
|
38
46
|
5. [Performance](#performance)
|
|
39
47
|
1. [Scenarios](#scenarios)
|
|
40
48
|
2. [Environment](#environment)
|
|
@@ -49,10 +57,10 @@ For more details about RedisSMQ design see [https://medium.com/@weyoss/building-
|
|
|
49
57
|
|
|
50
58
|
**2021.09.08**
|
|
51
59
|
|
|
52
|
-
- A major release v3
|
|
60
|
+
- A major release v3 is out.
|
|
53
61
|
- Upgrading your installation to the newest version should be straightforward as most APIs are compatible, [with some exceptions](docs/migrating-from-v2-to-v3.md).
|
|
54
62
|
- The project's code base has been migrated to TypeScript to make use of strong typings.
|
|
55
|
-
- JavaScript's users are always first class citizens
|
|
63
|
+
- JavaScript's users are always first class citizens.
|
|
56
64
|
|
|
57
65
|
See [CHANGELOG](CHANGELOG.md) for more details.
|
|
58
66
|
|
|
@@ -64,8 +72,8 @@ npm install redis-smq --save
|
|
|
64
72
|
|
|
65
73
|
Considerations:
|
|
66
74
|
|
|
67
|
-
-
|
|
68
|
-
Node.js version is recommended.
|
|
75
|
+
- RedisSMQ is targeted to be used in production environments. Therefore, only active LTS and maintenance LTS Node.js
|
|
76
|
+
releases (v12, v14, and v16) are supported. The latest stable Node.js version is recommended.
|
|
69
77
|
- Minimal Redis server version is 2.6.12.
|
|
70
78
|
|
|
71
79
|
# Configuration
|
|
@@ -133,11 +141,11 @@ module.exports = {
|
|
|
133
141
|
|
|
134
142
|
- `monitor` *(Object): Optional.* RedisSMQ monitor parameters.
|
|
135
143
|
|
|
136
|
-
- `monitor.enabled` *(Boolean/Integer): Optional.* Enable/Disable the monitor. By default disabled.
|
|
144
|
+
- `monitor.enabled` *(Boolean/Integer): Optional.* Enable/Disable the monitor. By default, disabled.
|
|
137
145
|
|
|
138
|
-
- `monitor.host` *(String): Optional.* IP address of the monitor server. By default `0.0.0.0`.
|
|
146
|
+
- `monitor.host` *(String): Optional.* IP address of the monitor server. By default, `0.0.0.0`.
|
|
139
147
|
|
|
140
|
-
- `monitor.port` *(Integer): Optional.* Port of the monitor server. By default `7210`.
|
|
148
|
+
- `monitor.port` *(Integer): Optional.* Port of the monitor server. By default, `7210`.
|
|
141
149
|
|
|
142
150
|
## Usage
|
|
143
151
|
|
|
@@ -149,11 +157,8 @@ Message class is the main component responsible for creating and handling messag
|
|
|
149
157
|
the required methods needed to construct and deal with messages.
|
|
150
158
|
|
|
151
159
|
```javascript
|
|
152
|
-
|
|
153
160
|
const { Message } = require('redis-smq');
|
|
154
|
-
|
|
155
161
|
const message = new Message();
|
|
156
|
-
|
|
157
162
|
message
|
|
158
163
|
.setBody({hello: 'world'})
|
|
159
164
|
.setTTL(3600000)
|
|
@@ -176,7 +181,7 @@ Each producer instance has an associated message queue and provides `produceMess
|
|
|
176
181
|
message and decides to either send it to the message queue scheduler or to immediately enqueue it for delivery.
|
|
177
182
|
|
|
178
183
|
```javascript
|
|
179
|
-
// filename: ./
|
|
184
|
+
// filename: ./examples/javascript/ns1-test-queue-producer.js
|
|
180
185
|
|
|
181
186
|
'use strict';
|
|
182
187
|
const { Message, Producer } = require('redis-smq');
|
|
@@ -185,8 +190,7 @@ const message = new Message();
|
|
|
185
190
|
|
|
186
191
|
message
|
|
187
192
|
.setBody({hello: 'world'})
|
|
188
|
-
.setTTL(3600000)
|
|
189
|
-
.setScheduledDelay(10);
|
|
193
|
+
.setTTL(3600000);
|
|
190
194
|
|
|
191
195
|
const producer = new Producer('test_queue');
|
|
192
196
|
producer.produceMessage(message, (err) => {
|
|
@@ -207,8 +211,7 @@ Consumer classes are saved per files. Each consumer file represents a consumer c
|
|
|
207
211
|
A consumer class may look like:
|
|
208
212
|
|
|
209
213
|
```javascript
|
|
210
|
-
// filename: ./
|
|
211
|
-
|
|
214
|
+
// filename: ./examples/javascript/ns1-test-queue-consumer.js
|
|
212
215
|
'use strict';
|
|
213
216
|
|
|
214
217
|
const { Consumer } = require('redis-smq');
|
|
@@ -242,7 +245,7 @@ To start consuming messages, a consumer needs first to be launched from CLI to c
|
|
|
242
245
|
and wait for messages:
|
|
243
246
|
|
|
244
247
|
```text
|
|
245
|
-
$ node ./
|
|
248
|
+
$ node ./examples/javascript/test-queue-consumer.js
|
|
246
249
|
```
|
|
247
250
|
|
|
248
251
|
Once a message is received and processed the consumer should acknowledge the message by invoking the callback function
|
|
@@ -257,6 +260,67 @@ corresponding queue called dead-letter queue where all failed to consume message
|
|
|
257
260
|
|
|
258
261
|
See [Consumer API Reference](docs/api/consumer.md) for more details.
|
|
259
262
|
|
|
263
|
+
### Message Scheduler
|
|
264
|
+
|
|
265
|
+
Message Scheduler enables you to schedule a one-time or repeating messages in your MQ server.
|
|
266
|
+
|
|
267
|
+
The [Message API](docs/api/message.md) provides many methods:
|
|
268
|
+
|
|
269
|
+
- [setScheduledPeriod()](docs/api/message.md#messageprototypesetscheduledperiod)
|
|
270
|
+
- [setScheduledDelay()](docs/api/message.md#messageprototypesetscheduleddelay)
|
|
271
|
+
- [setScheduledCron()](docs/api/message.md#messageprototypesetscheduledcron)
|
|
272
|
+
- [setScheduledRepeat()](docs/api/message.md#messageprototypesetscheduledrepeat)
|
|
273
|
+
|
|
274
|
+
in order to set up scheduling parameters for a specific message. Once your message is ready, you can use
|
|
275
|
+
[producer.produceMessage()](docs/api/producer.md#producerprototypeproducemessage) to publish it.
|
|
276
|
+
|
|
277
|
+
Under the hood, the `producer` invokes `isSchedulable()` and `schedule()` of the [Scheduler class](docs/api/scheduler.md)
|
|
278
|
+
to place your message in the delay queue.
|
|
279
|
+
|
|
280
|
+
```javascript
|
|
281
|
+
'use strict';
|
|
282
|
+
const { Message, Producer } = require('redis-smq');
|
|
283
|
+
|
|
284
|
+
const producer = new Producer('test_queue');
|
|
285
|
+
|
|
286
|
+
const message = new Message();
|
|
287
|
+
message
|
|
288
|
+
.setBody({hello: 'world'})
|
|
289
|
+
.setScheduledCron(`0 0 * * * *`);
|
|
290
|
+
|
|
291
|
+
producer.produceMessage(message, (err) => {
|
|
292
|
+
if (err) console.log(err);
|
|
293
|
+
else console.log('Message has been succefully produced');
|
|
294
|
+
})
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Alternatively, you can also manually get the scheduler instance from the producer using `producer.getScheduler()`
|
|
298
|
+
and call the `schedule()` method as shown in the example bellow:
|
|
299
|
+
|
|
300
|
+
```javascript
|
|
301
|
+
'use strict';
|
|
302
|
+
const { Message, Producer } = require('redis-smq');
|
|
303
|
+
|
|
304
|
+
const producer = new Producer('test_queue');
|
|
305
|
+
|
|
306
|
+
producer.getScheduler((err, scheduler) => {
|
|
307
|
+
if (err) console.log(err);
|
|
308
|
+
else {
|
|
309
|
+
const message = new Message();
|
|
310
|
+
message
|
|
311
|
+
.setBody({hello: 'world'})
|
|
312
|
+
.setScheduledCron(`0 0 * * * *`);
|
|
313
|
+
scheduler.schedule(message, (err, reply) => {
|
|
314
|
+
if (err) console.log(err);
|
|
315
|
+
else if (rely) console.log('Message has been succefully scheduled');
|
|
316
|
+
else console.log('Message has not been scheduled');
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
})
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
See [Scheduler API Reference](docs/api/scheduler.md) for more details.
|
|
323
|
+
|
|
260
324
|
## Performance
|
|
261
325
|
|
|
262
326
|
One key indicator about how RedisSMQ is fast and performant is Message throughput. Message throughput is the number of
|
|
@@ -315,23 +379,24 @@ $ node consumer | ./node_modules/.bin/bunyan
|
|
|
315
379
|
```
|
|
316
380
|
### Monitoring
|
|
317
381
|
|
|
318
|
-
The RedisSMQ Monitor is an interface which let you monitor and
|
|
382
|
+
The RedisSMQ Monitor is an interface which let you monitor, debug, and manage your RedisSMQ server from a web browser in
|
|
319
383
|
real-time.
|
|
320
384
|
|
|
321
|
-
Starting from version v1.1.0, RedisSMQ Monitor has split up into a standalone project and
|
|
322
|
-
[RedisSMQ Monitor](https://github.com/weyoss/redis-smq-monitor)
|
|
385
|
+
Starting from version v1.1.0, the frontend part of the RedisSMQ Monitor has split up into a standalone project and
|
|
386
|
+
is packaged under [RedisSMQ Monitor](https://github.com/weyoss/redis-smq-monitor)
|
|
323
387
|
|
|
324
|
-
|
|
388
|
+
Being an integral part of the MQ, the monitor can be launched and used by starting first the monitor server as shown
|
|
389
|
+
in the example bellow:
|
|
325
390
|
|
|
326
391
|
```javascript
|
|
327
|
-
// filename: ./
|
|
392
|
+
// filename: ./examples/javascript/monitor.js
|
|
328
393
|
'use strict';
|
|
329
394
|
|
|
330
395
|
const config = require('./config');
|
|
331
|
-
const {
|
|
396
|
+
const { MonitorServer } = require('redis-smq');
|
|
332
397
|
|
|
333
|
-
|
|
334
|
-
console.log('It works!')
|
|
398
|
+
MonitorServer(config).listen(() => {
|
|
399
|
+
console.log('It works!');
|
|
335
400
|
});
|
|
336
401
|
```
|
|
337
402
|
## Contributing
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -7,6 +7,6 @@ var producer_1 = require("./src/producer");
|
|
|
7
7
|
Object.defineProperty(exports, "Producer", { enumerable: true, get: function () { return producer_1.Producer; } });
|
|
8
8
|
var message_1 = require("./src/message");
|
|
9
9
|
Object.defineProperty(exports, "Message", { enumerable: true, get: function () { return message_1.Message; } });
|
|
10
|
-
var
|
|
11
|
-
Object.defineProperty(exports, "MonitorServer", { enumerable: true, get: function () { return
|
|
10
|
+
var monitor_server_1 = require("./src/monitor-server");
|
|
11
|
+
Object.defineProperty(exports, "MonitorServer", { enumerable: true, get: function () { return monitor_server_1.MonitorServer; } });
|
|
12
12
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;AAAA,2CAA0C;AAAjC,oGAAA,QAAQ,OAAA;AACjB,2CAA0C;AAAjC,oGAAA,QAAQ,OAAA;AACjB,yCAAwC;AAA/B,kGAAA,OAAO,OAAA;AAChB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;AAAA,2CAA0C;AAAjC,oGAAA,QAAQ,OAAA;AACjB,2CAA0C;AAAjC,oGAAA,QAAQ,OAAA;AACjB,yCAAwC;AAA/B,kGAAA,OAAO,OAAA;AAChB,uDAAqD;AAA5C,+GAAA,aAAa,OAAA"}
|
package/dist/src/consumer.d.ts
CHANGED
|
@@ -1,36 +1,34 @@
|
|
|
1
|
-
import { IConfig, IConsumerConstructorOptions,
|
|
1
|
+
import { IConfig, IConsumerConstructorOptions, ICallback, TUnaryFunction } from '../types';
|
|
2
2
|
import { Instance } from './instance';
|
|
3
3
|
import { Message } from './message';
|
|
4
4
|
import { ConsumerStatsProvider } from './stats-provider/consumer-stats-provider';
|
|
5
|
-
import {
|
|
5
|
+
import { Heartbeat } from './heartbeat';
|
|
6
6
|
import { GarbageCollector } from './gc';
|
|
7
|
+
import { SchedulerRunner } from './scheduler-runner';
|
|
8
|
+
import { RedisClient } from './redis-client';
|
|
7
9
|
export declare abstract class Consumer extends Instance {
|
|
8
|
-
protected readonly options: IConsumerConstructorOptions
|
|
9
|
-
protected
|
|
10
|
-
protected readonly consumerMessageConsumeTimeout: number;
|
|
11
|
-
protected readonly messageRetryThreshold: number;
|
|
12
|
-
protected readonly messageRetryDelay: number;
|
|
10
|
+
protected readonly options: Required<IConsumerConstructorOptions>;
|
|
11
|
+
protected schedulerRunnerInstance: SchedulerRunner | null;
|
|
13
12
|
protected statsProvider: ConsumerStatsProvider | null;
|
|
14
13
|
protected garbageCollectorInstance: GarbageCollector | null;
|
|
15
|
-
protected
|
|
14
|
+
protected heartbeatInstance: Heartbeat | null;
|
|
16
15
|
constructor(queueName: string, config?: IConfig, options?: IConsumerConstructorOptions);
|
|
17
16
|
getConsumerMessageConsumeTimeout(): number;
|
|
18
17
|
getMessageRetryThreshold(): number;
|
|
19
18
|
getConsumerMessageTTL(): number;
|
|
20
19
|
getMessageRetryDelay(): number;
|
|
21
|
-
getOptions(): IConsumerConstructorOptions
|
|
22
|
-
|
|
20
|
+
getOptions(): Required<IConsumerConstructorOptions>;
|
|
21
|
+
getStatsProvider(): ConsumerStatsProvider;
|
|
23
22
|
protected getNextMessage(): void;
|
|
24
23
|
protected hasGoneUp(): boolean;
|
|
25
24
|
protected hasGoneDown(): boolean;
|
|
26
25
|
protected registerEventsHandlers(): void;
|
|
27
|
-
protected
|
|
28
|
-
protected
|
|
29
|
-
protected
|
|
30
|
-
protected
|
|
31
|
-
protected
|
|
32
|
-
protected completeBootstrap(): void;
|
|
26
|
+
protected getGarbageCollectorInstance(cb: TUnaryFunction<GarbageCollector>): void;
|
|
27
|
+
protected getHeartBeatInstance(cb: TUnaryFunction<Heartbeat>): void;
|
|
28
|
+
protected getSchedulerRunnerInstance(cb: TUnaryFunction<SchedulerRunner>): void;
|
|
29
|
+
protected setupQueues(client: RedisClient, cb: ICallback<void>): void;
|
|
30
|
+
protected bootstrap(cb: ICallback<void>): void;
|
|
33
31
|
protected handleConsume(msg: Message): void;
|
|
34
32
|
protected handleConsumeFailure(msg: Message, error: Error): void;
|
|
35
|
-
abstract consume(msg: Message, cb:
|
|
33
|
+
abstract consume(msg: Message, cb: ICallback<void>): void;
|
|
36
34
|
}
|
package/dist/src/consumer.js
CHANGED
|
@@ -7,32 +7,34 @@ const consumer_stats_provider_1 = require("./stats-provider/consumer-stats-provi
|
|
|
7
7
|
const events_1 = require("./events");
|
|
8
8
|
const heartbeat_1 = require("./heartbeat");
|
|
9
9
|
const gc_1 = require("./gc");
|
|
10
|
-
const
|
|
10
|
+
const scheduler_runner_1 = require("./scheduler-runner");
|
|
11
|
+
const queue_helpers_1 = require("./queue-helpers");
|
|
11
12
|
class Consumer extends instance_1.Instance {
|
|
12
13
|
constructor(queueName, config = {}, options = {}) {
|
|
13
|
-
var _a, _b, _c, _d;
|
|
14
14
|
super(queueName, config);
|
|
15
|
+
this.options = {
|
|
16
|
+
messageTTL: 0,
|
|
17
|
+
messageConsumeTimeout: 0,
|
|
18
|
+
messageRetryThreshold: 3,
|
|
19
|
+
messageRetryDelay: 60,
|
|
20
|
+
};
|
|
21
|
+
this.schedulerRunnerInstance = null;
|
|
15
22
|
this.statsProvider = null;
|
|
16
23
|
this.garbageCollectorInstance = null;
|
|
17
|
-
this.
|
|
18
|
-
this.options = options;
|
|
19
|
-
this.consumerMessageTTL = +((_a = options.messageTTL) !== null && _a !== void 0 ? _a : 0);
|
|
20
|
-
this.consumerMessageConsumeTimeout = +((_b = options.messageConsumeTimeout) !== null && _b !== void 0 ? _b : 0);
|
|
21
|
-
this.messageRetryThreshold = +((_c = options.messageRetryThreshold) !== null && _c !== void 0 ? _c : 3);
|
|
22
|
-
this.messageRetryDelay = +((_d = options.messageRetryDelay) !== null && _d !== void 0 ? _d : 0);
|
|
23
|
-
this.redisKeys = new consumer_redis_keys_1.ConsumerRedisKeys(this.getQueueName(), this.getId());
|
|
24
|
+
this.heartbeatInstance = null;
|
|
25
|
+
this.options = Object.assign(Object.assign({}, this.options), options);
|
|
24
26
|
}
|
|
25
27
|
getConsumerMessageConsumeTimeout() {
|
|
26
|
-
return this.
|
|
28
|
+
return this.options.messageConsumeTimeout;
|
|
27
29
|
}
|
|
28
30
|
getMessageRetryThreshold() {
|
|
29
|
-
return this.messageRetryThreshold;
|
|
31
|
+
return this.options.messageRetryThreshold;
|
|
30
32
|
}
|
|
31
33
|
getConsumerMessageTTL() {
|
|
32
|
-
return this.
|
|
34
|
+
return this.options.messageTTL;
|
|
33
35
|
}
|
|
34
36
|
getMessageRetryDelay() {
|
|
35
|
-
return this.messageRetryDelay;
|
|
37
|
+
return this.options.messageRetryDelay;
|
|
36
38
|
}
|
|
37
39
|
getOptions() {
|
|
38
40
|
return this.options;
|
|
@@ -45,54 +47,59 @@ class Consumer extends instance_1.Instance {
|
|
|
45
47
|
}
|
|
46
48
|
getNextMessage() {
|
|
47
49
|
this.loggerInstance.info('Waiting for new messages...');
|
|
48
|
-
const { keyQueue, keyConsumerProcessingQueue } = this.
|
|
49
|
-
this.getRedisInstance(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (!json)
|
|
54
|
-
|
|
50
|
+
const { keyQueue, keyConsumerProcessingQueue } = this.redisKeys;
|
|
51
|
+
this.getRedisInstance((client) => {
|
|
52
|
+
client.brpoplpush(keyQueue, keyConsumerProcessingQueue, 0, (err, json) => {
|
|
53
|
+
if (err)
|
|
54
|
+
this.handleError(err);
|
|
55
|
+
else if (!json)
|
|
56
|
+
this.handleError(new Error('Expected a non empty string'));
|
|
57
|
+
else {
|
|
58
|
+
this.loggerInstance.info('Got new message...');
|
|
59
|
+
const message = message_1.Message.createFromMessage(json);
|
|
60
|
+
this.emit(events_1.events.MESSAGE_RECEIVED, message);
|
|
55
61
|
}
|
|
56
|
-
|
|
57
|
-
const message = message_1.Message.createFromMessage(json);
|
|
58
|
-
this.emit(events_1.events.MESSAGE_RECEIVED, message);
|
|
59
|
-
}
|
|
62
|
+
});
|
|
60
63
|
});
|
|
61
64
|
}
|
|
62
65
|
hasGoneUp() {
|
|
63
66
|
return (super.hasGoneUp() &&
|
|
64
67
|
this.startupFiredEvents.includes(events_1.events.GC_UP) &&
|
|
65
|
-
this.startupFiredEvents.includes(events_1.events.HEARTBEAT_UP)
|
|
68
|
+
this.startupFiredEvents.includes(events_1.events.HEARTBEAT_UP) &&
|
|
69
|
+
this.startupFiredEvents.includes(events_1.events.SCHEDULER_RUNNER_UP));
|
|
66
70
|
}
|
|
67
71
|
hasGoneDown() {
|
|
68
72
|
return (super.hasGoneDown() &&
|
|
69
73
|
this.shutdownFiredEvents.includes(events_1.events.GC_DOWN) &&
|
|
70
|
-
this.shutdownFiredEvents.includes(events_1.events.HEARTBEAT_DOWN)
|
|
74
|
+
this.shutdownFiredEvents.includes(events_1.events.HEARTBEAT_DOWN) &&
|
|
75
|
+
this.shutdownFiredEvents.includes(events_1.events.SCHEDULER_RUNNER_DOWN));
|
|
71
76
|
}
|
|
72
77
|
registerEventsHandlers() {
|
|
73
78
|
super.registerEventsHandlers();
|
|
74
79
|
this.on(events_1.events.HEARTBEAT_UP, () => this.handleStartupEvent(events_1.events.HEARTBEAT_UP));
|
|
75
|
-
this.on(events_1.events.HEARTBEAT_DOWN, () =>
|
|
80
|
+
this.on(events_1.events.HEARTBEAT_DOWN, () => {
|
|
81
|
+
this.heartbeatInstance = null;
|
|
82
|
+
this.handleShutdownEvent(events_1.events.HEARTBEAT_DOWN);
|
|
83
|
+
});
|
|
76
84
|
this.on(events_1.events.GC_UP, () => this.handleStartupEvent(events_1.events.GC_UP));
|
|
77
|
-
this.on(events_1.events.GC_DOWN, () =>
|
|
78
|
-
|
|
79
|
-
this.
|
|
85
|
+
this.on(events_1.events.GC_DOWN, () => {
|
|
86
|
+
this.garbageCollectorInstance = null;
|
|
87
|
+
this.handleShutdownEvent(events_1.events.GC_DOWN);
|
|
80
88
|
});
|
|
81
|
-
this.on(events_1.events.
|
|
82
|
-
|
|
89
|
+
this.on(events_1.events.SCHEDULER_RUNNER_UP, () => this.handleStartupEvent(events_1.events.SCHEDULER_RUNNER_UP));
|
|
90
|
+
this.on(events_1.events.SCHEDULER_RUNNER_DOWN, () => {
|
|
91
|
+
this.schedulerRunnerInstance = null;
|
|
92
|
+
this.handleShutdownEvent(events_1.events.SCHEDULER_RUNNER_DOWN);
|
|
83
93
|
});
|
|
84
94
|
this.on(events_1.events.GOING_UP, () => {
|
|
85
|
-
this.getHeartBeatInstance().start();
|
|
86
|
-
this.getGarbageCollectorInstance().start();
|
|
95
|
+
this.getHeartBeatInstance((hb) => hb.start());
|
|
96
|
+
this.getGarbageCollectorInstance((gc) => gc.start());
|
|
97
|
+
this.getSchedulerRunnerInstance((sr) => sr.start());
|
|
87
98
|
});
|
|
88
99
|
this.on(events_1.events.GOING_DOWN, () => {
|
|
89
|
-
this.getHeartBeatInstance().stop();
|
|
90
|
-
this.getGarbageCollectorInstance().stop();
|
|
91
|
-
|
|
92
|
-
this.on(events_1.events.DOWN, () => {
|
|
93
|
-
this.garbageCollectorInstance = null;
|
|
94
|
-
this.heartBeatInstance = null;
|
|
95
|
-
this.statsProvider = null;
|
|
100
|
+
this.getHeartBeatInstance((hb) => hb.stop());
|
|
101
|
+
this.getGarbageCollectorInstance((gc) => gc.stop());
|
|
102
|
+
this.getSchedulerRunnerInstance((sr) => sr.stop());
|
|
96
103
|
});
|
|
97
104
|
this.on(events_1.events.UP, () => {
|
|
98
105
|
this.emit(events_1.events.MESSAGE_NEXT);
|
|
@@ -103,26 +110,32 @@ class Consumer extends instance_1.Instance {
|
|
|
103
110
|
}
|
|
104
111
|
});
|
|
105
112
|
this.on(events_1.events.MESSAGE_RECEIVED, (message) => {
|
|
106
|
-
const messageCollector = this.getGarbageCollectorInstance().getMessageCollector();
|
|
107
113
|
if (this.powerManager.isRunning()) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
this.getGarbageCollectorInstance((gc) => {
|
|
115
|
+
gc.getMessageCollector((messageCollector) => {
|
|
116
|
+
if (this.statsProvider)
|
|
117
|
+
this.statsProvider.incrementProcessingSlot();
|
|
118
|
+
if (messageCollector.hasMessageExpired(message)) {
|
|
119
|
+
this.emit(events_1.events.MESSAGE_EXPIRED, message);
|
|
120
|
+
}
|
|
121
|
+
else
|
|
122
|
+
this.handleConsume(message);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
115
125
|
}
|
|
116
126
|
});
|
|
117
127
|
this.on(events_1.events.MESSAGE_EXPIRED, (message) => {
|
|
118
128
|
this.loggerInstance.info(`Message [${message.getId()}] has expired`);
|
|
119
129
|
const { keyConsumerProcessingQueue } = this.getInstanceRedisKeys();
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
130
|
+
this.getGarbageCollectorInstance((gc) => {
|
|
131
|
+
gc.getMessageCollector((messageCollector) => {
|
|
132
|
+
messageCollector.collectExpiredMessage(message, keyConsumerProcessingQueue, () => {
|
|
133
|
+
if (this.statsProvider)
|
|
134
|
+
this.statsProvider.incrementAcknowledgedSlot();
|
|
135
|
+
this.loggerInstance.info(`Message [${message.getId()}] successfully processed`);
|
|
136
|
+
this.emit(events_1.events.MESSAGE_NEXT);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
126
139
|
});
|
|
127
140
|
});
|
|
128
141
|
this.on(events_1.events.MESSAGE_ACKNOWLEDGED, () => {
|
|
@@ -134,52 +147,59 @@ class Consumer extends instance_1.Instance {
|
|
|
134
147
|
if (this.statsProvider)
|
|
135
148
|
this.statsProvider.incrementUnacknowledgedSlot();
|
|
136
149
|
const keys = this.getInstanceRedisKeys();
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
150
|
+
this.getGarbageCollectorInstance((gc) => {
|
|
151
|
+
gc.getMessageCollector((messageCollector) => {
|
|
152
|
+
messageCollector.collectMessage(msg, keys.keyConsumerProcessingQueue, (err) => {
|
|
153
|
+
if (err)
|
|
154
|
+
this.handleError(err);
|
|
155
|
+
else
|
|
156
|
+
this.emit(events_1.events.MESSAGE_NEXT);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
143
159
|
});
|
|
144
160
|
});
|
|
145
161
|
this.on(events_1.events.MESSAGE_CONSUME_TIMEOUT, (message) => {
|
|
146
162
|
this.handleConsumeFailure(message, new Error(`Consumer timed out after [${this.getConsumerMessageConsumeTimeout()}]`));
|
|
147
163
|
});
|
|
148
164
|
}
|
|
149
|
-
|
|
150
|
-
|
|
165
|
+
getGarbageCollectorInstance(cb) {
|
|
166
|
+
if (!this.garbageCollectorInstance)
|
|
167
|
+
this.emit(events_1.events.ERROR, new Error(`Expected an instance of GarbageCollector`));
|
|
168
|
+
else
|
|
169
|
+
cb(this.garbageCollectorInstance);
|
|
151
170
|
}
|
|
152
|
-
|
|
153
|
-
|
|
171
|
+
getHeartBeatInstance(cb) {
|
|
172
|
+
if (!this.heartbeatInstance)
|
|
173
|
+
this.emit(events_1.events.ERROR, new Error(`Expected an instance of HeartBeat`));
|
|
174
|
+
else
|
|
175
|
+
cb(this.heartbeatInstance);
|
|
154
176
|
}
|
|
155
|
-
|
|
156
|
-
if (!this.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
177
|
+
getSchedulerRunnerInstance(cb) {
|
|
178
|
+
if (!this.schedulerRunnerInstance)
|
|
179
|
+
this.emit(events_1.events.ERROR, new Error('Expected instance of SchedulerRunner'));
|
|
180
|
+
else
|
|
181
|
+
cb(this.schedulerRunnerInstance);
|
|
160
182
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
throw new Error(`Expected an instance of HeartBeat`);
|
|
164
|
-
}
|
|
165
|
-
return this.heartBeatInstance;
|
|
166
|
-
}
|
|
167
|
-
setupQueues() {
|
|
168
|
-
const { keyConsumerProcessingQueue, keyIndexQueueProcessing, keyIndexQueueQueuesProcessing, } = this.getInstanceRedisKeys();
|
|
169
|
-
const multi = this.getRedisInstance().multi();
|
|
170
|
-
multi.hset(keyIndexQueueQueuesProcessing, keyConsumerProcessingQueue, this.getId());
|
|
171
|
-
multi.sadd(keyIndexQueueProcessing, keyConsumerProcessingQueue);
|
|
172
|
-
this.getRedisInstance().execMulti(multi, (err) => {
|
|
183
|
+
setupQueues(client, cb) {
|
|
184
|
+
super.setupQueues(client, (err) => {
|
|
173
185
|
if (err)
|
|
174
|
-
|
|
175
|
-
else
|
|
176
|
-
|
|
186
|
+
cb(err);
|
|
187
|
+
else {
|
|
188
|
+
queue_helpers_1.queueHelpers.setupConsumerQueues(client, this.getQueueName(), this.getId(), cb);
|
|
189
|
+
}
|
|
177
190
|
});
|
|
178
191
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
192
|
+
bootstrap(cb) {
|
|
193
|
+
super.bootstrap((err) => {
|
|
194
|
+
if (err)
|
|
195
|
+
cb(err);
|
|
196
|
+
else {
|
|
197
|
+
this.heartbeatInstance = new heartbeat_1.Heartbeat(this);
|
|
198
|
+
this.garbageCollectorInstance = new gc_1.GarbageCollector(this);
|
|
199
|
+
this.schedulerRunnerInstance = new scheduler_runner_1.SchedulerRunner(this);
|
|
200
|
+
cb();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
183
203
|
}
|
|
184
204
|
handleConsume(msg) {
|
|
185
205
|
let isTimeout = false;
|
|
@@ -199,13 +219,15 @@ class Consumer extends instance_1.Instance {
|
|
|
199
219
|
}, consumeTimeout);
|
|
200
220
|
}
|
|
201
221
|
const acknowledgeMessage = () => {
|
|
202
|
-
this.getRedisInstance(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
222
|
+
this.getRedisInstance((client) => {
|
|
223
|
+
client.rpop(keys.keyConsumerProcessingQueue, (err) => {
|
|
224
|
+
if (err)
|
|
225
|
+
this.handleError(err);
|
|
226
|
+
else {
|
|
227
|
+
this.loggerInstance.info(`Message [${msg.getId()}] successfully processed`);
|
|
228
|
+
this.emit(events_1.events.MESSAGE_ACKNOWLEDGED, msg);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
209
231
|
});
|
|
210
232
|
};
|
|
211
233
|
const onConsumed = (err) => {
|