redis-smq 6.2.3 → 6.2.6
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 +16 -0
- package/dist/src/system/app/consumer/consumer-frontend.d.ts +2 -1
- package/dist/src/system/app/consumer/consumer-frontend.js +14 -3
- package/dist/src/system/app/consumer/consumer-heartbeat.d.ts +1 -1
- package/dist/src/system/app/consumer/consumer-heartbeat.js +17 -19
- package/dist/src/system/app/consumer/consumer-message-handler/message-handler-runner.d.ts +29 -0
- package/dist/src/system/app/consumer/consumer-message-handler/message-handler-runner.js +147 -0
- package/dist/src/system/app/consumer/{consumer-message-handler.d.ts → consumer-message-handler/message-handler.d.ts} +9 -8
- package/dist/src/system/app/consumer/{consumer-message-handler.js → consumer-message-handler/message-handler.js} +43 -20
- package/dist/src/system/app/consumer/consumer-message-handler/processing-queue.d.ts +6 -0
- package/dist/src/system/app/consumer/consumer-message-handler/processing-queue.js +63 -0
- package/dist/src/system/app/consumer/consumer-queues.d.ts +2 -3
- package/dist/src/system/app/consumer/consumer-queues.js +8 -13
- package/dist/src/system/app/consumer/consumer.d.ts +8 -22
- package/dist/src/system/app/consumer/consumer.js +32 -206
- package/dist/src/system/app/consumer/errors/message-handler-already-exists.error.d.ts +1 -1
- package/dist/src/system/app/consumer/errors/message-handler-already-exists.error.js +2 -2
- package/dist/src/system/app/message/message.js +5 -5
- package/dist/src/system/app/producer/producer.js +22 -23
- package/dist/src/system/app/queue-manager/queue-manager.d.ts +0 -3
- package/dist/src/system/app/queue-manager/queue-manager.js +0 -11
- package/dist/src/system/common/base.d.ts +1 -1
- package/dist/src/system/common/base.js +3 -4
- package/dist/src/system/common/message-rate-writer.d.ts +1 -1
- package/dist/src/system/common/message-rate-writer.js +13 -15
- package/dist/src/system/common/message-rate.d.ts +1 -1
- package/dist/src/system/common/message-rate.js +6 -8
- package/dist/src/system/common/redis-client/redis-client.js +2 -1
- package/dist/src/system/common/ticker/ticker.d.ts +1 -1
- package/dist/src/system/common/ticker/ticker.js +1 -1
- package/dist/src/system/common/worker/worker-runner/worker-runner.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 6.2.6 (2022-03-04)
|
|
4
|
+
|
|
5
|
+
* Clean up (2837cc6)
|
|
6
|
+
* Implement MessageHandlerRunner (cfba094)
|
|
7
|
+
|
|
8
|
+
## 6.2.5 (2022-03-03)
|
|
9
|
+
|
|
10
|
+
* Update Consumer API docs (8580f4a)
|
|
11
|
+
* Do not consume messages with and without priority from the same queue (84130bf)
|
|
12
|
+
* Use default parameters when creating a Ticker instance (db9feb0)
|
|
13
|
+
* Update consumer queue list upon shutting down a message handler (14519e2)
|
|
14
|
+
|
|
15
|
+
## 6.2.4 (2022-02-23)
|
|
16
|
+
|
|
17
|
+
* Fix consuming-messages/test00015 error (c5c365a)
|
|
18
|
+
|
|
3
19
|
## 6.2.3 (2022-02-23)
|
|
4
20
|
|
|
5
21
|
* Bump up redis-smq-monitor to v6.5.3 (4e845d0)
|
|
@@ -6,7 +6,8 @@ export declare class ConsumerFrontend extends EventEmitter {
|
|
|
6
6
|
constructor();
|
|
7
7
|
private registerEvents;
|
|
8
8
|
consume(queue: string | TQueueParams, usePriorityQueuing: boolean, messageHandler: TConsumerMessageHandler, cb: ICallback<boolean>): void;
|
|
9
|
-
cancel(queue: string | TQueueParams,
|
|
9
|
+
cancel(queue: string | TQueueParams, cb: ICallback<void>): void;
|
|
10
|
+
cancel(queue: string | TQueueParams, usePriorityQueuing: boolean, cb: ICallback<void>): void;
|
|
10
11
|
run(cb?: ICallback<boolean>): void;
|
|
11
12
|
shutdown(cb?: ICallback<boolean>): void;
|
|
12
13
|
isGoingUp(): boolean;
|
|
@@ -4,6 +4,8 @@ exports.ConsumerFrontend = void 0;
|
|
|
4
4
|
const events_1 = require("events");
|
|
5
5
|
const consumer_1 = require("./consumer");
|
|
6
6
|
const events_2 = require("../../common/events");
|
|
7
|
+
const argument_error_1 = require("../../common/errors/argument.error");
|
|
8
|
+
const queue_manager_1 = require("../queue-manager/queue-manager");
|
|
7
9
|
class ConsumerFrontend extends events_1.EventEmitter {
|
|
8
10
|
constructor() {
|
|
9
11
|
super();
|
|
@@ -21,10 +23,19 @@ class ConsumerFrontend extends events_1.EventEmitter {
|
|
|
21
23
|
.on(events_2.events.MESSAGE_RECEIVED, (...args) => this.emit(events_2.events.MESSAGE_RECEIVED, ...args));
|
|
22
24
|
}
|
|
23
25
|
consume(queue, usePriorityQueuing, messageHandler, cb) {
|
|
24
|
-
|
|
26
|
+
const queueParams = queue_manager_1.queueManager.getQueueParams(queue);
|
|
27
|
+
return this.consumer.consume(queueParams, usePriorityQueuing, messageHandler, cb);
|
|
25
28
|
}
|
|
26
|
-
cancel(queue,
|
|
27
|
-
|
|
29
|
+
cancel(queue, mixed, cb) {
|
|
30
|
+
const callback = (() => {
|
|
31
|
+
if (typeof mixed === 'function')
|
|
32
|
+
return mixed;
|
|
33
|
+
if (typeof mixed === 'boolean' && typeof cb === 'function')
|
|
34
|
+
return cb;
|
|
35
|
+
throw new argument_error_1.ArgumentError('Invalid arguments provided');
|
|
36
|
+
})();
|
|
37
|
+
const queueParams = queue_manager_1.queueManager.getQueueParams(queue);
|
|
38
|
+
this.consumer.cancel(queueParams, callback);
|
|
28
39
|
}
|
|
29
40
|
run(cb) {
|
|
30
41
|
this.consumer.run(cb);
|
|
@@ -13,7 +13,7 @@ export declare class ConsumerHeartbeat extends EventEmitter {
|
|
|
13
13
|
protected consumerId: string;
|
|
14
14
|
constructor(consumer: Consumer, redisClient: RedisClient);
|
|
15
15
|
protected getPayload(): THeartbeatPayload;
|
|
16
|
-
protected onTick()
|
|
16
|
+
protected onTick: () => void;
|
|
17
17
|
quit(cb: ICallback<void>): void;
|
|
18
18
|
static validateHeartbeatsOf(redisClient: RedisClient, consumerIds: string[], cb: ICallback<Record<string, boolean>>): void;
|
|
19
19
|
static getValidHeartbeats(redisClient: RedisClient, transform: boolean, cb: ICallback<{
|
|
@@ -34,15 +34,29 @@ function cpuUsage() {
|
|
|
34
34
|
class ConsumerHeartbeat extends events_2.EventEmitter {
|
|
35
35
|
constructor(consumer, redisClient) {
|
|
36
36
|
super();
|
|
37
|
+
this.onTick = () => {
|
|
38
|
+
const timestamp = Date.now();
|
|
39
|
+
const heartbeatPayload = this.getPayload();
|
|
40
|
+
const heartbeatPayloadStr = JSON.stringify(heartbeatPayload);
|
|
41
|
+
const multi = this.redisClient.multi();
|
|
42
|
+
multi.hset(this.keyHeartbeats, this.consumerId, heartbeatPayloadStr);
|
|
43
|
+
multi.zadd(this.keyHeartbeatTimestamps, timestamp, this.consumerId);
|
|
44
|
+
this.redisClient.execMulti(multi, (err) => {
|
|
45
|
+
if (err)
|
|
46
|
+
this.emit(events_1.events.ERROR, err);
|
|
47
|
+
else {
|
|
48
|
+
this.emit(events_1.events.HEARTBEAT_TICK, timestamp, this.consumerId, heartbeatPayload);
|
|
49
|
+
this.ticker.nextTick();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
};
|
|
37
53
|
this.redisClient = redisClient;
|
|
38
54
|
this.consumerId = consumer.getId();
|
|
39
55
|
const { keyHeartbeats } = consumer.getRedisKeys();
|
|
40
56
|
this.keyHeartbeats = keyHeartbeats;
|
|
41
57
|
this.keyHeartbeatTimestamps =
|
|
42
58
|
redis_keys_1.redisKeys.getMainKeys().keyHeartbeatInstanceIds;
|
|
43
|
-
this.ticker = new ticker_1.Ticker(
|
|
44
|
-
this.onTick();
|
|
45
|
-
}, 1000);
|
|
59
|
+
this.ticker = new ticker_1.Ticker(this.onTick);
|
|
46
60
|
this.ticker.nextTick();
|
|
47
61
|
}
|
|
48
62
|
getPayload() {
|
|
@@ -59,22 +73,6 @@ class ConsumerHeartbeat extends events_2.EventEmitter {
|
|
|
59
73
|
},
|
|
60
74
|
};
|
|
61
75
|
}
|
|
62
|
-
onTick() {
|
|
63
|
-
const timestamp = Date.now();
|
|
64
|
-
const heartbeatPayload = this.getPayload();
|
|
65
|
-
const heartbeatPayloadStr = JSON.stringify(heartbeatPayload);
|
|
66
|
-
const multi = this.redisClient.multi();
|
|
67
|
-
multi.hset(this.keyHeartbeats, this.consumerId, heartbeatPayloadStr);
|
|
68
|
-
multi.zadd(this.keyHeartbeatTimestamps, timestamp, this.consumerId);
|
|
69
|
-
this.redisClient.execMulti(multi, (err) => {
|
|
70
|
-
if (err)
|
|
71
|
-
this.emit(events_1.events.ERROR, err);
|
|
72
|
-
else {
|
|
73
|
-
this.emit(events_1.events.HEARTBEAT_TICK, timestamp, this.consumerId, heartbeatPayload);
|
|
74
|
-
this.ticker.nextTick();
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
76
|
quit(cb) {
|
|
79
77
|
(0, async_1.waterfall)([
|
|
80
78
|
(cb) => {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Consumer } from '../consumer';
|
|
2
|
+
import { MessageHandler } from './message-handler';
|
|
3
|
+
import { ICallback, ICompatibleLogger, TConsumerMessageHandler, TConsumerMessageHandlerParams, TQueueParams } from '../../../../../types';
|
|
4
|
+
import { RedisClient } from '../../../common/redis-client/redis-client';
|
|
5
|
+
import { ConsumerMessageRate } from '../consumer-message-rate';
|
|
6
|
+
export declare class MessageHandlerRunner {
|
|
7
|
+
private readonly consumer;
|
|
8
|
+
private redisClient;
|
|
9
|
+
private messageHandlerInstances;
|
|
10
|
+
private messageHandlers;
|
|
11
|
+
private config;
|
|
12
|
+
protected logger: ICompatibleLogger;
|
|
13
|
+
constructor(consumer: Consumer);
|
|
14
|
+
protected registerMessageHandlerEvents: (messageHandler: MessageHandler) => void;
|
|
15
|
+
protected getMessageHandlerInstance: (queue: TQueueParams) => MessageHandler | undefined;
|
|
16
|
+
protected getMessageHandler(queue: TQueueParams): TConsumerMessageHandlerParams | undefined;
|
|
17
|
+
protected createMessageRateInstance: (queue: TQueueParams, redisClient: RedisClient) => ConsumerMessageRate;
|
|
18
|
+
protected runMessageHandler: (handlerParams: TConsumerMessageHandlerParams, cb: ICallback<void>) => void;
|
|
19
|
+
protected shutdownMessageHandler: (messageHandler: MessageHandler, cb: ICallback<void>) => void;
|
|
20
|
+
protected getRedisClient(): RedisClient;
|
|
21
|
+
run: (redisClient: RedisClient, cb: ICallback<void>) => void;
|
|
22
|
+
shutdown: (cb: ICallback<void>) => void;
|
|
23
|
+
removeMessageHandler: (queue: TQueueParams, cb: ICallback<void>) => void;
|
|
24
|
+
addMessageHandler: (queue: TQueueParams, usePriorityQueuing: boolean, messageHandler: TConsumerMessageHandler, cb: ICallback<boolean>) => void;
|
|
25
|
+
getQueues: () => {
|
|
26
|
+
queue: TQueueParams;
|
|
27
|
+
usingPriorityQueuing: boolean;
|
|
28
|
+
}[];
|
|
29
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MessageHandlerRunner = void 0;
|
|
4
|
+
const message_handler_1 = require("./message-handler");
|
|
5
|
+
const events_1 = require("../../../common/events");
|
|
6
|
+
const redis_client_1 = require("../../../common/redis-client/redis-client");
|
|
7
|
+
const empty_callback_reply_error_1 = require("../../../common/errors/empty-callback-reply.error");
|
|
8
|
+
const async_1 = require("../../../lib/async");
|
|
9
|
+
const configuration_1 = require("../../../common/configuration/configuration");
|
|
10
|
+
const logger_1 = require("../../../common/logger");
|
|
11
|
+
const consumer_message_rate_1 = require("../consumer-message-rate");
|
|
12
|
+
const consumer_message_rate_writer_1 = require("../consumer-message-rate-writer");
|
|
13
|
+
const message_handler_already_exists_error_1 = require("../errors/message-handler-already-exists.error");
|
|
14
|
+
const panic_error_1 = require("../../../common/errors/panic.error");
|
|
15
|
+
class MessageHandlerRunner {
|
|
16
|
+
constructor(consumer) {
|
|
17
|
+
this.redisClient = null;
|
|
18
|
+
this.messageHandlerInstances = [];
|
|
19
|
+
this.messageHandlers = [];
|
|
20
|
+
this.registerMessageHandlerEvents = (messageHandler) => {
|
|
21
|
+
messageHandler.on(events_1.events.ERROR, (...args) => this.consumer.emit(events_1.events.ERROR, ...args));
|
|
22
|
+
messageHandler.on(events_1.events.IDLE, (...args) => this.consumer.emit(events_1.events.IDLE, ...args));
|
|
23
|
+
messageHandler.on(events_1.events.MESSAGE_UNACKNOWLEDGED, (...args) => this.consumer.emit(events_1.events.MESSAGE_UNACKNOWLEDGED, ...args));
|
|
24
|
+
messageHandler.on(events_1.events.MESSAGE_DEAD_LETTERED, (...args) => this.consumer.emit(events_1.events.MESSAGE_DEAD_LETTERED, ...args));
|
|
25
|
+
messageHandler.on(events_1.events.MESSAGE_ACKNOWLEDGED, (...args) => this.consumer.emit(events_1.events.MESSAGE_ACKNOWLEDGED, ...args));
|
|
26
|
+
};
|
|
27
|
+
this.getMessageHandlerInstance = (queue) => {
|
|
28
|
+
return this.messageHandlerInstances.find((i) => {
|
|
29
|
+
const q = i.getQueue();
|
|
30
|
+
return q.name === queue.name && q.ns === queue.ns;
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
this.createMessageRateInstance = (queue, redisClient) => {
|
|
34
|
+
const messageRateWriter = new consumer_message_rate_writer_1.ConsumerMessageRateWriter(redisClient, queue, this.consumer.getId());
|
|
35
|
+
return new consumer_message_rate_1.ConsumerMessageRate(messageRateWriter);
|
|
36
|
+
};
|
|
37
|
+
this.runMessageHandler = (handlerParams, cb) => {
|
|
38
|
+
redis_client_1.RedisClient.getNewInstance((err, client) => {
|
|
39
|
+
if (err)
|
|
40
|
+
cb(err);
|
|
41
|
+
else if (!client)
|
|
42
|
+
cb(new empty_callback_reply_error_1.EmptyCallbackReplyError());
|
|
43
|
+
else {
|
|
44
|
+
const redisClient = this.getRedisClient();
|
|
45
|
+
const { queue, usePriorityQueuing, messageHandler } = handlerParams;
|
|
46
|
+
const messageRate = this.config.monitor.enabled
|
|
47
|
+
? this.createMessageRateInstance(queue, redisClient)
|
|
48
|
+
: null;
|
|
49
|
+
const handler = new message_handler_1.MessageHandler(this.consumer.getId(), queue, messageHandler, usePriorityQueuing, client, messageRate);
|
|
50
|
+
this.registerMessageHandlerEvents(handler);
|
|
51
|
+
this.messageHandlerInstances.push(handler);
|
|
52
|
+
this.logger.info(`Created a new instance (ID: ${handler.getId()}) for MessageHandler (${JSON.stringify(handlerParams)}).`);
|
|
53
|
+
handler.run(cb);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
this.shutdownMessageHandler = (messageHandler, cb) => {
|
|
58
|
+
const queue = messageHandler.getQueue();
|
|
59
|
+
const redisClient = this.getRedisClient();
|
|
60
|
+
messageHandler.shutdown(redisClient, () => {
|
|
61
|
+
this.messageHandlerInstances = this.messageHandlerInstances.filter((handler) => {
|
|
62
|
+
const q = handler.getQueue();
|
|
63
|
+
return !(q.name === queue.name && q.ns === queue.ns);
|
|
64
|
+
});
|
|
65
|
+
cb();
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
this.run = (redisClient, cb) => {
|
|
69
|
+
this.redisClient = redisClient;
|
|
70
|
+
(0, async_1.each)(this.messageHandlers, (handlerParams, _, done) => {
|
|
71
|
+
this.runMessageHandler(handlerParams, done);
|
|
72
|
+
}, cb);
|
|
73
|
+
};
|
|
74
|
+
this.shutdown = (cb) => {
|
|
75
|
+
(0, async_1.each)(this.messageHandlerInstances, (handler, queue, done) => {
|
|
76
|
+
this.shutdownMessageHandler(handler, done);
|
|
77
|
+
}, (err) => {
|
|
78
|
+
if (err)
|
|
79
|
+
cb(err);
|
|
80
|
+
else {
|
|
81
|
+
this.redisClient = null;
|
|
82
|
+
cb();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
this.removeMessageHandler = (queue, cb) => {
|
|
87
|
+
const handler = this.getMessageHandler(queue);
|
|
88
|
+
if (!handler)
|
|
89
|
+
cb();
|
|
90
|
+
else {
|
|
91
|
+
this.messageHandlers = this.messageHandlers.filter((handler) => {
|
|
92
|
+
const q = handler.queue;
|
|
93
|
+
return !(q.name === queue.name && q.ns === queue.ns);
|
|
94
|
+
});
|
|
95
|
+
this.logger.info(`Message handler with parameters (${JSON.stringify(queue)}) has been removed.`);
|
|
96
|
+
const handlerInstance = this.getMessageHandlerInstance(queue);
|
|
97
|
+
if (handlerInstance)
|
|
98
|
+
this.shutdownMessageHandler(handlerInstance, cb);
|
|
99
|
+
else
|
|
100
|
+
cb();
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
this.addMessageHandler = (queue, usePriorityQueuing, messageHandler, cb) => {
|
|
104
|
+
const handler = this.getMessageHandler(queue);
|
|
105
|
+
if (handler)
|
|
106
|
+
cb(new message_handler_already_exists_error_1.MessageHandlerAlreadyExistsError(queue));
|
|
107
|
+
else {
|
|
108
|
+
const handlerParams = {
|
|
109
|
+
queue,
|
|
110
|
+
usePriorityQueuing,
|
|
111
|
+
messageHandler,
|
|
112
|
+
};
|
|
113
|
+
this.messageHandlers.push(handlerParams);
|
|
114
|
+
this.logger.info(`Message handler with parameters (${JSON.stringify(handlerParams)}) has been registered.`);
|
|
115
|
+
if (this.consumer.isRunning())
|
|
116
|
+
this.runMessageHandler(handlerParams, (err) => {
|
|
117
|
+
if (err)
|
|
118
|
+
cb(err);
|
|
119
|
+
else
|
|
120
|
+
cb(null, true);
|
|
121
|
+
});
|
|
122
|
+
else
|
|
123
|
+
cb(null, false);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
this.getQueues = () => {
|
|
127
|
+
return this.messageHandlers.map((i) => ({
|
|
128
|
+
queue: i.queue,
|
|
129
|
+
usingPriorityQueuing: i.usePriorityQueuing,
|
|
130
|
+
}));
|
|
131
|
+
};
|
|
132
|
+
this.consumer = consumer;
|
|
133
|
+
this.config = (0, configuration_1.getConfiguration)();
|
|
134
|
+
this.logger = (0, logger_1.getNamespacedLogger)(`${consumer.constructor.name}/${consumer.getId()}/MessageHandlerRunner`);
|
|
135
|
+
}
|
|
136
|
+
getMessageHandler(queue) {
|
|
137
|
+
return this.messageHandlers.find((i) => i.queue.name === queue.name && i.queue.ns === queue.ns);
|
|
138
|
+
}
|
|
139
|
+
getRedisClient() {
|
|
140
|
+
if (!this.redisClient) {
|
|
141
|
+
throw new panic_error_1.PanicError('Expected a non-empty value');
|
|
142
|
+
}
|
|
143
|
+
return this.redisClient;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
exports.MessageHandlerRunner = MessageHandlerRunner;
|
|
147
|
+
//# sourceMappingURL=message-handler-runner.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { EMessageUnacknowledgedCause, ICallback, ICompatibleLogger, TConsumerMessageHandler, TQueueConsumerRedisKeys, TQueueParams, TQueueRateLimit } from '
|
|
3
|
-
import { RedisClient } from '
|
|
4
|
-
import { Message } from '
|
|
2
|
+
import { EMessageUnacknowledgedCause, ICallback, ICompatibleLogger, TConsumerMessageHandler, TQueueConsumerRedisKeys, TQueueParams, TQueueRateLimit, TRedisClientMulti } from '../../../../../types';
|
|
3
|
+
import { RedisClient } from '../../../common/redis-client/redis-client';
|
|
4
|
+
import { Message } from '../../message/message';
|
|
5
5
|
import { EventEmitter } from 'events';
|
|
6
|
-
import { PowerManager } from '
|
|
7
|
-
import { ConsumerMessageRate } from '
|
|
8
|
-
import { Ticker } from '
|
|
9
|
-
export declare class
|
|
6
|
+
import { PowerManager } from '../../../common/power-manager/power-manager';
|
|
7
|
+
import { ConsumerMessageRate } from '../consumer-message-rate';
|
|
8
|
+
import { Ticker } from '../../../common/ticker/ticker';
|
|
9
|
+
export declare class MessageHandler extends EventEmitter {
|
|
10
10
|
protected id: string;
|
|
11
11
|
protected consumerId: string;
|
|
12
12
|
protected queue: TQueueParams;
|
|
@@ -33,10 +33,11 @@ export declare class ConsumerMessageHandler extends EventEmitter {
|
|
|
33
33
|
protected dequeueMessage(cb: ICallback<string>): void;
|
|
34
34
|
protected dequeue(cb: ICallback<string>): void;
|
|
35
35
|
run: (cb: ICallback<void>) => void;
|
|
36
|
-
shutdown: (cb: ICallback<void>) => void;
|
|
36
|
+
shutdown: (redisClient: RedisClient, cb: ICallback<void>) => void;
|
|
37
37
|
getQueue(): TQueueParams;
|
|
38
38
|
isUsingPriorityQueuing(): boolean;
|
|
39
39
|
getConsumerId(): string;
|
|
40
40
|
getRedisKeys(): TQueueConsumerRedisKeys;
|
|
41
41
|
getId(): string;
|
|
42
|
+
static cleanUp(redisClient: RedisClient, consumerId: string, queue: TQueueParams, pendingMulti: TRedisClientMulti | undefined, cb: ICallback<void>): void;
|
|
42
43
|
}
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const types_1 = require("
|
|
3
|
+
exports.MessageHandler = void 0;
|
|
4
|
+
const types_1 = require("../../../../../types");
|
|
5
5
|
const uuid_1 = require("uuid");
|
|
6
|
-
const message_1 = require("
|
|
7
|
-
const events_1 = require("
|
|
8
|
-
const consumer_error_1 = require("
|
|
9
|
-
const redis_keys_1 = require("
|
|
6
|
+
const message_1 = require("../../message/message");
|
|
7
|
+
const events_1 = require("../../../common/events");
|
|
8
|
+
const consumer_error_1 = require("../errors/consumer.error");
|
|
9
|
+
const redis_keys_1 = require("../../../common/redis-keys/redis-keys");
|
|
10
10
|
const events_2 = require("events");
|
|
11
|
-
const power_manager_1 = require("
|
|
12
|
-
const empty_callback_reply_error_1 = require("
|
|
13
|
-
const consumer_queues_1 = require("
|
|
14
|
-
const broker_1 = require("
|
|
15
|
-
const queue_manager_1 = require("
|
|
16
|
-
const ticker_1 = require("
|
|
17
|
-
const logger_1 = require("
|
|
18
|
-
const async_1 = require("
|
|
19
|
-
|
|
11
|
+
const power_manager_1 = require("../../../common/power-manager/power-manager");
|
|
12
|
+
const empty_callback_reply_error_1 = require("../../../common/errors/empty-callback-reply.error");
|
|
13
|
+
const consumer_queues_1 = require("../consumer-queues");
|
|
14
|
+
const broker_1 = require("../../../common/broker/broker");
|
|
15
|
+
const queue_manager_1 = require("../../queue-manager/queue-manager");
|
|
16
|
+
const ticker_1 = require("../../../common/ticker/ticker");
|
|
17
|
+
const logger_1 = require("../../../common/logger");
|
|
18
|
+
const async_1 = require("../../../lib/async");
|
|
19
|
+
const processing_queue_1 = require("./processing-queue");
|
|
20
|
+
class MessageHandler extends events_2.EventEmitter {
|
|
20
21
|
constructor(consumerId, queue, handler, usePriorityQueuing, redisClient, messageRate = null) {
|
|
21
22
|
super();
|
|
22
23
|
this.messageRate = null;
|
|
@@ -31,7 +32,7 @@ class ConsumerMessageHandler extends events_2.EventEmitter {
|
|
|
31
32
|
const multi = this.redisClient.multi();
|
|
32
33
|
queue_manager_1.queueManager.setUpMessageQueue(multi, this.queue);
|
|
33
34
|
consumer_queues_1.consumerQueues.addConsumer(multi, this.queue, this.consumerId);
|
|
34
|
-
|
|
35
|
+
processing_queue_1.processingQueue.setUpProcessingQueue(multi, this.queue, this.consumerId);
|
|
35
36
|
this.redisClient.execMulti(multi, (err) => {
|
|
36
37
|
if (err)
|
|
37
38
|
cb(err);
|
|
@@ -44,7 +45,7 @@ class ConsumerMessageHandler extends events_2.EventEmitter {
|
|
|
44
45
|
}
|
|
45
46
|
});
|
|
46
47
|
};
|
|
47
|
-
this.shutdown = (cb) => {
|
|
48
|
+
this.shutdown = (redisClient, cb) => {
|
|
48
49
|
const goDown = () => {
|
|
49
50
|
this.powerManager.goingDown();
|
|
50
51
|
(0, async_1.waterfall)([
|
|
@@ -58,6 +59,9 @@ class ConsumerMessageHandler extends events_2.EventEmitter {
|
|
|
58
59
|
else
|
|
59
60
|
cb();
|
|
60
61
|
},
|
|
62
|
+
(cb) => {
|
|
63
|
+
MessageHandler.cleanUp(redisClient, this.consumerId, this.queue, undefined, cb);
|
|
64
|
+
},
|
|
61
65
|
(cb) => {
|
|
62
66
|
this.redisClient.halt(cb);
|
|
63
67
|
},
|
|
@@ -97,7 +101,7 @@ class ConsumerMessageHandler extends events_2.EventEmitter {
|
|
|
97
101
|
this.emit(events_1.events.IDLE, this.queue);
|
|
98
102
|
});
|
|
99
103
|
}
|
|
100
|
-
this.ticker = new ticker_1.Ticker(
|
|
104
|
+
this.ticker = new ticker_1.Ticker();
|
|
101
105
|
}
|
|
102
106
|
registerEventsHandlers() {
|
|
103
107
|
this.on(events_1.events.UP, () => {
|
|
@@ -263,6 +267,25 @@ class ConsumerMessageHandler extends events_2.EventEmitter {
|
|
|
263
267
|
getId() {
|
|
264
268
|
return this.id;
|
|
265
269
|
}
|
|
270
|
+
static cleanUp(redisClient, consumerId, queue, pendingMulti, cb) {
|
|
271
|
+
const multi = pendingMulti !== null && pendingMulti !== void 0 ? pendingMulti : redisClient.multi();
|
|
272
|
+
(0, async_1.waterfall)([
|
|
273
|
+
(cb) => {
|
|
274
|
+
processing_queue_1.processingQueue.cleanUpProcessingQueue(redisClient, consumerId, queue, multi, cb);
|
|
275
|
+
},
|
|
276
|
+
(cb) => {
|
|
277
|
+
consumer_queues_1.consumerQueues.removeConsumer(multi, queue, consumerId);
|
|
278
|
+
cb();
|
|
279
|
+
},
|
|
280
|
+
], (err) => {
|
|
281
|
+
if (err)
|
|
282
|
+
cb(err);
|
|
283
|
+
else if (pendingMulti)
|
|
284
|
+
cb();
|
|
285
|
+
else
|
|
286
|
+
redisClient.execMulti(multi, (err) => cb(err));
|
|
287
|
+
});
|
|
288
|
+
}
|
|
266
289
|
}
|
|
267
|
-
exports.
|
|
268
|
-
//# sourceMappingURL=
|
|
290
|
+
exports.MessageHandler = MessageHandler;
|
|
291
|
+
//# sourceMappingURL=message-handler.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { RedisClient } from '../../../common/redis-client/redis-client';
|
|
2
|
+
import { ICallback, TQueueParams, TRedisClientMulti } from '../../../../../types';
|
|
3
|
+
export declare const processingQueue: {
|
|
4
|
+
cleanUpProcessingQueue(redisClient: RedisClient, consumerId: string, queue: TQueueParams, multi: TRedisClientMulti, cb: ICallback<void>): void;
|
|
5
|
+
setUpProcessingQueue(multi: TRedisClientMulti, queue: TQueueParams, consumerId: string): void;
|
|
6
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processingQueue = void 0;
|
|
4
|
+
const types_1 = require("../../../../../types");
|
|
5
|
+
const message_1 = require("../../message/message");
|
|
6
|
+
const async_1 = require("../../../lib/async");
|
|
7
|
+
const broker_1 = require("../../../common/broker/broker");
|
|
8
|
+
const time_series_1 = require("../../../common/time-series/time-series");
|
|
9
|
+
const global_dead_lettered_time_series_1 = require("../consumer-time-series/global-dead-lettered-time-series");
|
|
10
|
+
const queue_dead_lettered_time_series_1 = require("../consumer-time-series/queue-dead-lettered-time-series");
|
|
11
|
+
const redis_keys_1 = require("../../../common/redis-keys/redis-keys");
|
|
12
|
+
function fetchProcessingQueueMessage(redisClient, consumerId, keyQueueProcessing, cb) {
|
|
13
|
+
redisClient.lrange(keyQueueProcessing, 0, 0, (err, range) => {
|
|
14
|
+
if (err)
|
|
15
|
+
cb(err);
|
|
16
|
+
else if (range && range.length) {
|
|
17
|
+
const msg = message_1.Message.createFromMessage(range[0]);
|
|
18
|
+
cb(null, msg);
|
|
19
|
+
}
|
|
20
|
+
else
|
|
21
|
+
cb();
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function deleteProcessingQueue(multi, queue, processingQueue) {
|
|
25
|
+
const { keyProcessingQueues, keyQueueProcessingQueues } = redis_keys_1.redisKeys.getQueueKeys(queue);
|
|
26
|
+
multi.srem(keyProcessingQueues, processingQueue);
|
|
27
|
+
multi.hdel(keyQueueProcessingQueues, processingQueue);
|
|
28
|
+
multi.del(processingQueue);
|
|
29
|
+
}
|
|
30
|
+
exports.processingQueue = {
|
|
31
|
+
cleanUpProcessingQueue(redisClient, consumerId, queue, multi, cb) {
|
|
32
|
+
const { keyQueueProcessing } = redis_keys_1.redisKeys.getQueueConsumerKeys(queue, consumerId);
|
|
33
|
+
(0, async_1.waterfall)([
|
|
34
|
+
(cb) => {
|
|
35
|
+
fetchProcessingQueueMessage(redisClient, consumerId, keyQueueProcessing, (err, msg) => {
|
|
36
|
+
if (err)
|
|
37
|
+
cb(err);
|
|
38
|
+
else if (msg) {
|
|
39
|
+
const deadLettered = broker_1.broker.retry(multi, keyQueueProcessing, msg, types_1.EMessageUnacknowledgedCause.RECOVERY);
|
|
40
|
+
if (typeof deadLettered === 'string') {
|
|
41
|
+
const timestamp = time_series_1.TimeSeries.getCurrentTimestamp();
|
|
42
|
+
(0, global_dead_lettered_time_series_1.GlobalDeadLetteredTimeSeries)(redisClient).add(timestamp, 1, multi);
|
|
43
|
+
(0, queue_dead_lettered_time_series_1.QueueDeadLetteredTimeSeries)(redisClient, queue).add(timestamp, 1, multi);
|
|
44
|
+
}
|
|
45
|
+
cb();
|
|
46
|
+
}
|
|
47
|
+
else
|
|
48
|
+
cb();
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
(cb) => {
|
|
52
|
+
deleteProcessingQueue(multi, queue, keyQueueProcessing);
|
|
53
|
+
cb();
|
|
54
|
+
},
|
|
55
|
+
], cb);
|
|
56
|
+
},
|
|
57
|
+
setUpProcessingQueue(multi, queue, consumerId) {
|
|
58
|
+
const { keyQueueProcessing, keyProcessingQueues, keyQueueProcessingQueues, } = redis_keys_1.redisKeys.getQueueConsumerKeys(queue, consumerId);
|
|
59
|
+
multi.hset(keyQueueProcessingQueues, keyQueueProcessing, consumerId);
|
|
60
|
+
multi.sadd(keyProcessingQueues, keyQueueProcessing);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=processing-queue.js.map
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { ICallback, THeartbeatRegistryPayload, TQueueParams, TRedisClientMulti } from '../../../../types';
|
|
2
2
|
import { RedisClient } from '../../common/redis-client/redis-client';
|
|
3
3
|
export declare const consumerQueues: {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exists(client: RedisClient, keyRegistry: string, instanceId: string, cb: ICallback<boolean>): void;
|
|
4
|
+
removeConsumer(multi: TRedisClientMulti, queue: TQueueParams, consumerId: string): void;
|
|
5
|
+
addConsumer(multi: TRedisClientMulti, queue: TQueueParams, consumerId: string): void;
|
|
7
6
|
getQueueConsumers(client: RedisClient, queue: TQueueParams, transform: boolean, cb: ICallback<Record<string, THeartbeatRegistryPayload | string>>): void;
|
|
8
7
|
getQueueConsumerIds(client: RedisClient, queue: TQueueParams, cb: ICallback<string[]>): void;
|
|
9
8
|
countQueueConsumers(client: RedisClient, queue: TQueueParams, cb: ICallback<number>): void;
|
|
@@ -19,26 +19,21 @@ const IPAddresses = (() => {
|
|
|
19
19
|
return addresses;
|
|
20
20
|
})();
|
|
21
21
|
exports.consumerQueues = {
|
|
22
|
-
|
|
22
|
+
removeConsumer(multi, queue, consumerId) {
|
|
23
|
+
const { keyQueueConsumers, keyConsumerQueues } = redis_keys_1.redisKeys.getQueueConsumerKeys(queue, consumerId);
|
|
24
|
+
multi.hdel(keyQueueConsumers, consumerId);
|
|
25
|
+
multi.srem(keyConsumerQueues, JSON.stringify(queue));
|
|
26
|
+
},
|
|
27
|
+
addConsumer(multi, queue, consumerId) {
|
|
23
28
|
const data = {
|
|
24
29
|
ipAddress: IPAddresses,
|
|
25
30
|
hostname: os.hostname(),
|
|
26
31
|
pid: process.pid,
|
|
27
32
|
createdAt: Date.now(),
|
|
28
33
|
};
|
|
29
|
-
const { keyQueueConsumers, keyConsumerQueues } = redis_keys_1.redisKeys.getQueueConsumerKeys(queue,
|
|
34
|
+
const { keyQueueConsumers, keyConsumerQueues } = redis_keys_1.redisKeys.getQueueConsumerKeys(queue, consumerId);
|
|
30
35
|
multi.sadd(keyConsumerQueues, JSON.stringify(queue));
|
|
31
|
-
multi.hset(keyQueueConsumers,
|
|
32
|
-
},
|
|
33
|
-
removeConsumer(multi, consumerId, queues) {
|
|
34
|
-
(0, async_1.each)(queues, (queue, _, done) => {
|
|
35
|
-
const { keyQueueConsumers } = redis_keys_1.redisKeys.getQueueKeys(queue);
|
|
36
|
-
multi.hdel(keyQueueConsumers, consumerId);
|
|
37
|
-
done();
|
|
38
|
-
}, () => void 0);
|
|
39
|
-
},
|
|
40
|
-
exists(client, keyRegistry, instanceId, cb) {
|
|
41
|
-
client.hexists(keyRegistry, instanceId, cb);
|
|
36
|
+
multi.hset(keyQueueConsumers, consumerId, JSON.stringify(data));
|
|
42
37
|
},
|
|
43
38
|
getQueueConsumers(client, queue, transform, cb) {
|
|
44
39
|
const { keyQueueConsumers } = redis_keys_1.redisKeys.getQueueKeys(queue);
|
|
@@ -1,43 +1,29 @@
|
|
|
1
|
-
import { ICallback, TConsumerMessageHandler,
|
|
2
|
-
import { ConsumerMessageRate } from './consumer-message-rate';
|
|
1
|
+
import { ICallback, TConsumerMessageHandler, TConsumerRedisKeys, THeartbeatRegistryPayload, TQueueParams, TUnaryFunction, TRedisClientMulti } from '../../../../types';
|
|
3
2
|
import { RedisClient } from '../../common/redis-client/redis-client';
|
|
4
3
|
import { Base } from '../../common/base';
|
|
5
|
-
import { ConsumerMessageHandler } from './consumer-message-handler';
|
|
6
|
-
import { Message } from '../message/message';
|
|
7
4
|
export declare class Consumer extends Base {
|
|
5
|
+
private readonly redisKeys;
|
|
6
|
+
private readonly messageHandlerRunner;
|
|
8
7
|
private heartbeat;
|
|
9
8
|
private workerRunner;
|
|
10
|
-
private messageHandlerInstances;
|
|
11
|
-
private messageHandlers;
|
|
12
|
-
private readonly redisKeys;
|
|
13
9
|
constructor();
|
|
14
|
-
protected registerMessageHandlerEvents: (messageHandler: ConsumerMessageHandler) => void;
|
|
15
10
|
protected setUpHeartbeat: (cb: ICallback<void>) => void;
|
|
16
11
|
protected tearDownHeartbeat: (cb: ICallback<void>) => void;
|
|
17
12
|
protected setUpConsumerWorkers: (cb: ICallback<void>) => void;
|
|
18
13
|
protected tearDownConsumerWorkers: (cb: ICallback<void>) => void;
|
|
19
|
-
protected
|
|
20
|
-
protected
|
|
21
|
-
protected tearDownMessageHandlerInstances: (cb: ICallback<void>) => void;
|
|
22
|
-
protected createMessageRateInstance: (queue: TQueueParams, redisClient: RedisClient) => ConsumerMessageRate;
|
|
14
|
+
protected runMessageHandlers: (cb: ICallback<void>) => void;
|
|
15
|
+
protected shutdownMessageHandlers: (cb: ICallback<void>) => void;
|
|
23
16
|
protected goingUp(): TUnaryFunction<ICallback<void>>[];
|
|
24
17
|
protected goingDown(): TUnaryFunction<ICallback<void>>[];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
protected getMessageHandlerInstance: (queue: TQueueParams, usePriorityQueuing: boolean) => ConsumerMessageHandler | undefined;
|
|
28
|
-
protected removeMessageHandlerInstance: (queue: TQueueParams, usePriorityQueuing: boolean) => void;
|
|
29
|
-
protected removeMessageHandler: (queue: TQueueParams, usePriorityQueuing: boolean) => void;
|
|
30
|
-
consume(queue: string | TQueueParams, usePriorityQueuing: boolean, messageHandler: TConsumerMessageHandler, cb: ICallback<boolean>): void;
|
|
31
|
-
cancel(queue: string | TQueueParams, usePriorityQueuing: boolean, cb: ICallback<void>): void;
|
|
32
|
-
getRedisKeys(): TConsumerRedisKeys;
|
|
18
|
+
consume(queue: TQueueParams, usePriorityQueuing: boolean, messageHandler: TConsumerMessageHandler, cb: ICallback<boolean>): void;
|
|
19
|
+
cancel(queue: TQueueParams, cb: ICallback<void>): void;
|
|
33
20
|
getQueues(): {
|
|
34
21
|
queue: TQueueParams;
|
|
35
22
|
usingPriorityQueuing: boolean;
|
|
36
23
|
}[];
|
|
24
|
+
getRedisKeys(): TConsumerRedisKeys;
|
|
37
25
|
static getOnlineConsumers(redisClient: RedisClient, queue: TQueueParams, transform: boolean | undefined, cb: ICallback<Record<string, THeartbeatRegistryPayload | string>>): void;
|
|
38
26
|
static getOnlineConsumerIds(redisClient: RedisClient, queue: TQueueParams, cb: ICallback<string[]>): void;
|
|
39
27
|
static countOnlineConsumers(redisClient: RedisClient, queue: TQueueParams, cb: ICallback<number>): void;
|
|
40
28
|
static handleOfflineConsumer(multi: TRedisClientMulti, redisClient: RedisClient, consumerId: string, cb: ICallback<void>): void;
|
|
41
|
-
protected static fetchProcessingQueueMessage(redisClient: RedisClient, consumerId: string, keyQueueProcessing: string, cb: ICallback<Message>): void;
|
|
42
|
-
protected static handleConsumerProcessingQueue(multi: TRedisClientMulti, redisClient: RedisClient, consumerId: string, queue: TQueueParams, cb: ICallback<void>): void;
|
|
43
29
|
}
|