redis-smq 7.0.0-rc.5 → 7.0.0-rc.8

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.
Files changed (51) hide show
  1. package/.codecov.yml +5 -0
  2. package/CHANGELOG.md +24 -0
  3. package/README.md +18 -15
  4. package/dist/index.d.ts +0 -1
  5. package/dist/index.js +1 -4
  6. package/dist/src/common/event-listeners/event-provider.d.ts +8 -0
  7. package/dist/src/common/event-listeners/event-provider.js +13 -0
  8. package/dist/src/common/redis-keys/redis-keys.js +1 -1
  9. package/dist/src/config/configuration.js +2 -0
  10. package/dist/src/config/event-listeners/event-listeners.d.ts +2 -0
  11. package/dist/src/config/event-listeners/event-listeners.js +14 -0
  12. package/dist/src/lib/base.js +0 -2
  13. package/dist/src/lib/consumer/consumer-heartbeat.d.ts +3 -3
  14. package/dist/src/lib/consumer/consumer-heartbeat.js +12 -14
  15. package/dist/src/lib/{broker → consumer/consumer-message-handler}/acknowledge-message.d.ts +2 -2
  16. package/dist/src/lib/{broker → consumer/consumer-message-handler}/acknowledge-message.js +1 -1
  17. package/dist/src/lib/consumer/consumer-message-handler/consume-message.d.ts +4 -2
  18. package/dist/src/lib/consumer/consumer-message-handler/consume-message.js +18 -17
  19. package/dist/src/lib/{broker → consumer/consumer-message-handler}/dead-letter-message.d.ts +2 -2
  20. package/dist/src/lib/{broker → consumer/consumer-message-handler}/dead-letter-message.js +1 -1
  21. package/dist/src/lib/{broker → consumer/consumer-message-handler}/delay-message.d.ts +2 -2
  22. package/dist/src/lib/{broker → consumer/consumer-message-handler}/delay-message.js +1 -1
  23. package/dist/src/lib/consumer/consumer-message-handler/message-handler.d.ts +7 -4
  24. package/dist/src/lib/consumer/consumer-message-handler/message-handler.js +53 -30
  25. package/dist/src/lib/consumer/consumer-message-handler/multiplexed-message-handler/multiplexed-message-handler.js +3 -16
  26. package/dist/src/lib/consumer/consumer-message-handler/processing-queue.d.ts +3 -1
  27. package/dist/src/lib/consumer/consumer-message-handler/processing-queue.js +11 -5
  28. package/dist/src/lib/{broker → consumer/consumer-message-handler}/requeue-message.d.ts +2 -2
  29. package/dist/src/lib/{broker → consumer/consumer-message-handler}/requeue-message.js +1 -1
  30. package/dist/src/lib/consumer/consumer-message-handler/retry-message.d.ts +15 -0
  31. package/dist/src/lib/{broker → consumer/consumer-message-handler}/retry-message.js +26 -8
  32. package/dist/src/lib/consumer/consumer.d.ts +13 -11
  33. package/dist/src/lib/consumer/consumer.js +2 -2
  34. package/dist/src/lib/producer/producer.d.ts +3 -3
  35. package/dist/src/lib/producer/producer.js +8 -8
  36. package/dist/src/lib/{broker → producer}/schedule-message.d.ts +0 -0
  37. package/dist/src/lib/{broker → producer}/schedule-message.js +1 -1
  38. package/dist/src/workers/delay.worker.js +1 -1
  39. package/dist/src/workers/{heartbeat-monitor.worker.d.ts → watchdog.worker.d.ts} +5 -4
  40. package/dist/src/workers/watchdog.worker.js +74 -0
  41. package/dist/types/index.d.ts +17 -9
  42. package/dist/types/index.js +2 -2
  43. package/package.json +2 -2
  44. package/dist/src/lib/broker/retry-message.d.ts +0 -6
  45. package/dist/src/lib/consumer/offline-consumers.d.ts +0 -4
  46. package/dist/src/lib/consumer/offline-consumers.js +0 -18
  47. package/dist/src/plugins/errors/plugin-registration-not-allowed-error.d.ts +0 -4
  48. package/dist/src/plugins/errors/plugin-registration-not-allowed-error.js +0 -11
  49. package/dist/src/plugins/plugins.d.ts +0 -6
  50. package/dist/src/plugins/plugins.js +0 -35
  51. package/dist/src/workers/heartbeat-monitor.worker.js +0 -23
package/.codecov.yml ADDED
@@ -0,0 +1,5 @@
1
+ coverage:
2
+ status:
3
+ patch:
4
+ default:
5
+ target: 80%
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 7.0.0-rc.8 (2022-06-09)
4
+
5
+ * Update docs (96a45e7)
6
+ * Test consumers/producers event listeners (856e12d)
7
+ * Implement consumers/producers event listeners (6f5d603)
8
+
9
+ ## 7.0.0-rc.7 (2022-06-07)
10
+
11
+ * Update redis keys prefix (a6ca852)
12
+ * Use codecov instead of coveralls (d8b5f83)
13
+ * Improve consuming-messages/test00013 (5cd823c)
14
+ * Improve consuming-messages/test00010 (a9a4f47)
15
+ * Test WatchdogWorker (73fbe9a)
16
+ * Clean up (aa9a51a)
17
+ * Improve unacknowleged messages handling, refactor (005c6a0)
18
+ * Fix outdated javascript examples (e31f89c)
19
+ * Keep a clean directory structure (642739f)
20
+ * Update README.md (5c011e3)
21
+ * Clean up tests (10ebb77)
22
+
23
+ ## 7.0.0-rc.6 (2022-05-31)
24
+
25
+ * Bump up redis-smq-common to v1.0.0-rc.11 (43717f0)
26
+
3
27
  ## 7.0.0-rc.5 (2022-05-31)
4
28
 
5
29
  * Bump up redis-smq-common to v1.0.0-rc.10 (e025525)
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  <p>
9
9
  <a href="https://github.com/weyoss/redis-smq/actions/workflows/tests.yml"><img src="https://github.com/weyoss/redis-smq/actions/workflows/tests.yml/badge.svg" alt="Tests" style="max-width:100%;" /></a>
10
- <a href="https://coveralls.io/r/weyoss/redis-smq?branch=master" rel="nofollow"><img src="https://img.shields.io/coveralls/github/weyoss/redis-smq.svg" alt="Coverage Status" /></a>
10
+ <a href="https://codecov.io/github/weyoss/redis-smq?branch=master" rel="nofollow"><img src="https://img.shields.io/codecov/c/github/weyoss/redis-smq" alt="Coverage Status" /></a>
11
11
  <a href="https://npmjs.org/package/redis-smq" rel="nofollow"><img src="https://img.shields.io/npm/v/redis-smq.svg" alt="NPM version" /></a>
12
12
  <a href="https://npmjs.org/package/redis-smq" rel="nofollow"><img src="https://img.shields.io/npm/dm/redis-smq.svg" alt="NPM downloads" /></a>
13
13
  <a href="https://lgtm.com/projects/g/weyoss/redis-smq/context:javascript" rel="nofollow"><img src="https://img.shields.io/lgtm/grade/javascript/github/weyoss/redis-smq.svg?logo=lgtm&logoWidth=18" alt="Code quality" /></a>
@@ -53,6 +53,7 @@ RedisSMQ is a Node.js library for queuing messages (aka jobs) and processing the
53
53
  1. [Message Class](#message-class)
54
54
  2. [Producer Class](#producer-class)
55
55
  3. [Consumer Class](#consumer-class)
56
+ 1. [Message Acknowledgement](#message-acknowledgement)
56
57
  2. Advanced Topics
57
58
  1. [Scheduling Messages](/docs/scheduling-messages.md)
58
59
  2. [Priority Queues](/docs/priority-queues.md)
@@ -133,7 +134,7 @@ See [Message Reference](/docs/api/message.md) for more details.
133
134
 
134
135
  #### Producer Class
135
136
 
136
- `Producer` class allows you to publish a message to a queue.
137
+ A `Producer` instance allows you to publish a message to a queue.
137
138
 
138
139
  You can use a single `Producer` instance to produce messages, including messages with priority, to multiple queues.
139
140
 
@@ -166,19 +167,17 @@ See [Producer Reference](/docs/api/producer.md) for more details.
166
167
 
167
168
  #### Consumer Class
168
169
 
169
- `Consumer` class can be used to receive and consume messages from a queue.
170
+ A `Consumer` instance can be used to receive and consume messages from one or multiple queues.
170
171
 
171
- Similarly to a `Producer` instance, a `Consumer` instance can consume messages from multiple queues.
172
+ To consume messages from a queue, the `Consumer` class provides the [consume()](/docs/api/consumer.md#consumerprototypeconsume) method which allows you to register a `message handler`.
172
173
 
173
- For consuming messages from a queue, the `Consumer` class provides the [consume()](/docs/api/consumer.md#consumerprototypeconsume) method which allows you to register a `message handler`.
174
+ A `message handler` is a function that receives a delivered message from a given queue.
174
175
 
175
- A `message handler` is a function which get called once a message is received.
176
+ Message handlers can be registered at any time, before or after a consumer has been started.
176
177
 
177
- Message handlers can be registered at any time, before or after you have started your consumer.
178
+ In contrast to producers, consumers are not automatically started upon creation. To start a consumer use the [run()](/docs/api/consumer.md#consumerprototyperun) method.
178
179
 
179
- A consumer can be started using the [run()](/docs/api/consumer.md#consumerprototyperun) method.
180
-
181
- To shut down and remove a given `message handler` from your consumer, use the [cancel()](/docs/api/consumer.md#consumerprototypecancel) method.
180
+ To stop consuming messages from a queue and to remove the associated `message handler` from your consumer, use the [cancel()](/docs/api/consumer.md#consumerprototypecancel) method.
182
181
 
183
182
  To shut down completely your consumer and tear down all message handlers, use the [shutdown()](/docs/api/consumer.md#consumerprototypeshutdown) method.
184
183
 
@@ -202,17 +201,21 @@ consumer.consume('test_queue', messageHandler, (err) => {
202
201
  consumer.run();
203
202
  ```
204
203
 
204
+ ##### Message Acknowledgement
205
+
205
206
  Once a message is received, to acknowledge it, you invoke the callback function without arguments, as shown in the example above.
206
207
 
207
- Message acknowledgment informs the MQ that a message has been successfully consumed.
208
+ Message acknowledgment informs the MQ that the delivered message has been successfully consumed.
209
+
210
+ If an error occurred while processing a message, you can unacknowledge it by passing in the error to the callback function.
208
211
 
209
- If an error occurred while processing a message, you can unacknowledge the message by passing the error to the callback function.
212
+ By default, unacknowledged messages are re-queued and delivered again unless **message retry threshold** is exceeded.
210
213
 
211
- By default, unacknowledged messages are re-queued and delivered again unless **message retry threshold** is exceeded. Then the messages are moved to a **dead-letter queue (DLQ)**.
214
+ Delivered messages that couldn't be processed or can not be delivered to consumers are moved to a system generated queue called **dead-letter queue (DLQ)**.
212
215
 
213
- A `dead-letter queue` is a system generated queue that holds all messages that couldn't be processed or can not be delivered to consumers.
216
+ By default, RedisSMQ does not store acknowledged and dead-lettered messages for saving disk and memory spaces, and also to increase message processing performance.
214
217
 
215
- By default, RedisSMQ does not store acknowledged and dead-lettered messages for saving disk and memory space, and also to increase message processing performance. If you need such feature, you can enable it from your [configuration](/docs/configuration.md) object.
218
+ If you need such feature, you can enable it from your [configuration](/docs/configuration.md) object.
216
219
 
217
220
  See [Consumer Reference](/docs/api/consumer.md) for more details.
218
221
 
package/dist/index.d.ts CHANGED
@@ -4,4 +4,3 @@ export { Producer } from './src/lib/producer/producer';
4
4
  export { Message } from './src/lib/message/message';
5
5
  export { MessageManager } from './src/lib/message-manager/message-manager';
6
6
  export { QueueManager } from './src/lib/queue-manager/queue-manager';
7
- export { registerProducerPlugin, registerConsumerPlugin, } from './src/plugins/plugins';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerConsumerPlugin = exports.registerProducerPlugin = exports.QueueManager = exports.MessageManager = exports.Message = exports.Producer = exports.Consumer = exports.events = void 0;
3
+ exports.QueueManager = exports.MessageManager = exports.Message = exports.Producer = exports.Consumer = exports.events = void 0;
4
4
  var events_1 = require("./src/common/events/events");
5
5
  Object.defineProperty(exports, "events", { enumerable: true, get: function () { return events_1.events; } });
6
6
  var consumer_1 = require("./src/lib/consumer/consumer");
@@ -13,7 +13,4 @@ var message_manager_1 = require("./src/lib/message-manager/message-manager");
13
13
  Object.defineProperty(exports, "MessageManager", { enumerable: true, get: function () { return message_manager_1.MessageManager; } });
14
14
  var queue_manager_1 = require("./src/lib/queue-manager/queue-manager");
15
15
  Object.defineProperty(exports, "QueueManager", { enumerable: true, get: function () { return queue_manager_1.QueueManager; } });
16
- var plugins_1 = require("./src/plugins/plugins");
17
- Object.defineProperty(exports, "registerProducerPlugin", { enumerable: true, get: function () { return plugins_1.registerProducerPlugin; } });
18
- Object.defineProperty(exports, "registerConsumerPlugin", { enumerable: true, get: function () { return plugins_1.registerConsumerPlugin; } });
19
16
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,8 @@
1
+ /// <reference types="node" />
2
+ import { IEventProvider } from '../../../types';
3
+ import { EventEmitter } from 'events';
4
+ export declare class EventProvider implements IEventProvider {
5
+ protected eventEmitter: EventEmitter;
6
+ constructor(eventEmitter: EventEmitter);
7
+ on(event: string, listener: (...args: any[]) => void): void;
8
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventProvider = void 0;
4
+ class EventProvider {
5
+ constructor(eventEmitter) {
6
+ this.eventEmitter = eventEmitter;
7
+ }
8
+ on(event, listener) {
9
+ this.eventEmitter.on(event, listener);
10
+ }
11
+ }
12
+ exports.EventProvider = EventProvider;
13
+ //# sourceMappingURL=event-provider.js.map
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.redisKeys = void 0;
4
4
  const redis_keys_error_1 = require("./redis-keys.error");
5
5
  const keySegmentSeparator = ':';
6
- const nsPrefix = 'redis-smq-v700-rc0';
6
+ const nsPrefix = 'redis-smq-v7';
7
7
  const globalNamespace = 'global';
8
8
  var ERedisKey;
9
9
  (function (ERedisKey) {
@@ -5,12 +5,14 @@ const namespace_1 = require("./namespace");
5
5
  const redis_1 = require("./redis");
6
6
  const logger_1 = require("./logger");
7
7
  const messages_1 = require("./messages/messages");
8
+ const event_listeners_1 = require("./event-listeners/event-listeners");
8
9
  function getConfiguration(config = {}) {
9
10
  return {
10
11
  namespace: (0, namespace_1.default)(config),
11
12
  redis: (0, redis_1.default)(config),
12
13
  logger: (0, logger_1.default)(config),
13
14
  messages: (0, messages_1.default)(config),
15
+ eventListeners: (0, event_listeners_1.EventListeners)(config),
14
16
  };
15
17
  }
16
18
  exports.getConfiguration = getConfiguration;
@@ -0,0 +1,2 @@
1
+ import { IConfig, TRequiredEventListenersConfig } from '../../../types';
2
+ export declare function EventListeners(userConfig: IConfig): TRequiredEventListenersConfig;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventListeners = void 0;
4
+ const lodash_1 = require("lodash");
5
+ const defaultConfig = {
6
+ consumerEventListeners: [],
7
+ producerEventListeners: [],
8
+ };
9
+ function EventListeners(userConfig) {
10
+ const { eventListeners = {} } = userConfig;
11
+ return (0, lodash_1.merge)({}, defaultConfig, eventListeners);
12
+ }
13
+ exports.EventListeners = EventListeners;
14
+ //# sourceMappingURL=event-listeners.js.map
@@ -6,7 +6,6 @@ const events_1 = require("events");
6
6
  const events_2 = require("../common/events/events");
7
7
  const configuration_1 = require("../config/configuration");
8
8
  const redis_smq_common_1 = require("redis-smq-common");
9
- const plugins_1 = require("../plugins/plugins");
10
9
  class Base extends events_1.EventEmitter {
11
10
  constructor(config) {
12
11
  super();
@@ -38,7 +37,6 @@ class Base extends events_1.EventEmitter {
38
37
  this.config = (0, configuration_1.getConfiguration)(config);
39
38
  this.logger = redis_smq_common_1.logger.getNamespacedLogger(this.config.logger, `${this.constructor.name.toLowerCase()}:${this.id}`);
40
39
  this.registerEventsHandlers();
41
- (0, plugins_1.disablePluginRegistration)();
42
40
  }
43
41
  registerEventsHandlers() {
44
42
  this.on(events_2.events.GOING_UP, () => this.logger.info(`Going up...`));
@@ -1,9 +1,9 @@
1
1
  /// <reference types="node" />
2
- import { IRequiredConfig, TConsumerHeartbeat } from '../../../types';
2
+ import { TConsumerHeartbeat } from '../../../types';
3
3
  import { RedisClient, Ticker } from 'redis-smq-common';
4
4
  import { EventEmitter } from 'events';
5
5
  import { Consumer } from './consumer';
6
- import { ICallback } from 'redis-smq-common/dist/types';
6
+ import { ICallback, IRedisClientMulti } from 'redis-smq-common/dist/types';
7
7
  export declare class ConsumerHeartbeat extends EventEmitter {
8
8
  protected static readonly heartbeatTTL: number;
9
9
  protected redisClient: RedisClient;
@@ -22,5 +22,5 @@ export declare class ConsumerHeartbeat extends EventEmitter {
22
22
  }[]>): void;
23
23
  static getValidHeartbeatIds(redisClient: RedisClient, cb: ICallback<string[]>): void;
24
24
  static getExpiredHeartbeatIds(redisClient: RedisClient, cb: ICallback<string[]>): void;
25
- static handleExpiredHeartbeatIds(config: IRequiredConfig, redisClient: RedisClient, consumerIds: string[], cb: ICallback<void>): void;
25
+ static handleExpiredHeartbeatId(consumerId: string | string[], multi: IRedisClientMulti): void;
26
26
  }
@@ -7,7 +7,6 @@ const events_1 = require("../../common/events/events");
7
7
  const redis_keys_1 = require("../../common/redis-keys/redis-keys");
8
8
  const events_2 = require("events");
9
9
  const redis_smq_common_2 = require("redis-smq-common");
10
- const offline_consumers_1 = require("./offline-consumers");
11
10
  const cpuUsageStatsRef = {
12
11
  cpuUsage: process.cpuUsage(),
13
12
  time: process.hrtime(),
@@ -77,7 +76,11 @@ class ConsumerHeartbeat extends events_2.EventEmitter {
77
76
  this.ticker.once(events_1.events.DOWN, cb);
78
77
  this.ticker.quit();
79
78
  },
80
- (cb) => ConsumerHeartbeat.handleExpiredHeartbeatIds(this.consumer.getConfig(), this.redisClient, [this.consumer.getId()], (err) => cb(err)),
79
+ (cb) => {
80
+ const multi = this.redisClient.multi();
81
+ ConsumerHeartbeat.handleExpiredHeartbeatId(this.consumer.getId(), multi);
82
+ multi.exec((err) => cb(err));
83
+ },
81
84
  (cb) => this.redisClient.halt(cb),
82
85
  ], cb);
83
86
  }
@@ -163,18 +166,13 @@ class ConsumerHeartbeat extends events_2.EventEmitter {
163
166
  cb(null, consumerIds !== null && consumerIds !== void 0 ? consumerIds : []);
164
167
  });
165
168
  }
166
- static handleExpiredHeartbeatIds(config, redisClient, consumerIds, cb) {
167
- if (consumerIds.length) {
168
- const { keyHeartbeats, keyHeartbeatConsumerWeight } = redis_keys_1.redisKeys.getMainKeys();
169
- const multi = redisClient.multi();
170
- redis_smq_common_2.async.each(consumerIds, (consumerId, _, done) => {
171
- multi.hdel(keyHeartbeats, consumerId);
172
- multi.zrem(keyHeartbeatConsumerWeight, consumerId);
173
- (0, offline_consumers_1.handleOfflineConsumer)(config, multi, redisClient, consumerId, done);
174
- }, () => multi.exec((err) => cb(err)));
175
- }
176
- else
177
- cb();
169
+ static handleExpiredHeartbeatId(consumerId, multi) {
170
+ const { keyHeartbeats, keyHeartbeatConsumerWeight } = redis_keys_1.redisKeys.getMainKeys();
171
+ const ids = typeof consumerId === 'string' ? [consumerId] : consumerId;
172
+ ids.forEach((consumerId) => {
173
+ multi.hdel(keyHeartbeats, consumerId);
174
+ multi.zrem(keyHeartbeatConsumerWeight, consumerId);
175
+ });
178
176
  }
179
177
  }
180
178
  exports.ConsumerHeartbeat = ConsumerHeartbeat;
@@ -1,5 +1,5 @@
1
1
  import { RedisClient } from 'redis-smq-common';
2
- import { Message } from '../message/message';
2
+ import { Message } from '../../message/message';
3
3
  import { ICallback } from 'redis-smq-common/dist/types';
4
- import { IRequiredConfig } from '../../../types';
4
+ import { IRequiredConfig } from '../../../../types';
5
5
  export declare function acknowledgeMessage(config: IRequiredConfig, redisClient: RedisClient, message: Message, keyQueueProcessing: string, cb: ICallback<void>): void;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.acknowledgeMessage = void 0;
4
- const redis_keys_1 = require("../../common/redis-keys/redis-keys");
4
+ const redis_keys_1 = require("../../../common/redis-keys/redis-keys");
5
5
  function acknowledgeMessage(config, redisClient, message, keyQueueProcessing, cb) {
6
6
  const queue = message.getRequiredQueue();
7
7
  const { store, queueSize, expire } = config.messages.store.acknowledged;
@@ -2,12 +2,14 @@ import { Message } from '../../message/message';
2
2
  import { EMessageUnacknowledgedCause } from '../../../../types';
3
3
  import { MessageHandler } from './message-handler';
4
4
  import { RedisClient } from 'redis-smq-common';
5
+ import { ICompatibleLogger } from 'redis-smq-common/dist/types';
5
6
  export declare class ConsumeMessage {
6
7
  protected keyQueueProcessing: string;
7
8
  protected messageHandler: MessageHandler;
8
9
  protected redisClient: RedisClient;
9
- constructor(messageHandler: MessageHandler, redisClient: RedisClient);
10
- protected unacknowledgeMessage(msg: Message, cause: EMessageUnacknowledgedCause, err?: Error): void;
10
+ protected logger: ICompatibleLogger;
11
+ constructor(messageHandler: MessageHandler, redisClient: RedisClient, logger: ICompatibleLogger);
12
+ protected unacknowledgeMessage(msg: Message, cause: EMessageUnacknowledgedCause): void;
11
13
  protected consumeMessage(msg: Message): void;
12
14
  handleReceivedMessage(message: Message): void;
13
15
  }
@@ -4,27 +4,28 @@ exports.ConsumeMessage = void 0;
4
4
  const message_1 = require("../../message/message");
5
5
  const types_1 = require("../../../../types");
6
6
  const events_1 = require("../../../common/events/events");
7
- const consumer_error_1 = require("../errors/consumer.error");
8
7
  const redis_keys_1 = require("../../../common/redis-keys/redis-keys");
9
- const retry_message_1 = require("../../broker/retry-message");
10
- const acknowledge_message_1 = require("../../broker/acknowledge-message");
8
+ const redis_smq_common_1 = require("redis-smq-common");
9
+ const retry_message_1 = require("./retry-message");
10
+ const acknowledge_message_1 = require("./acknowledge-message");
11
11
  class ConsumeMessage {
12
- constructor(messageHandler, redisClient) {
12
+ constructor(messageHandler, redisClient, logger) {
13
13
  this.redisClient = redisClient;
14
14
  this.messageHandler = messageHandler;
15
15
  const { keyQueueProcessing } = redis_keys_1.redisKeys.getQueueConsumerKeys(messageHandler.getQueue(), messageHandler.getConsumerId());
16
16
  this.keyQueueProcessing = keyQueueProcessing;
17
+ this.logger = logger;
17
18
  }
18
- unacknowledgeMessage(msg, cause, err) {
19
- if (err) {
20
- }
21
- (0, retry_message_1.retryMessage)(this.messageHandler.getConfig(), this.redisClient, this.keyQueueProcessing, msg, cause, (err, deadLetterCause) => {
19
+ unacknowledgeMessage(msg, cause) {
20
+ (0, retry_message_1.retryMessage)(this.messageHandler.getConfig(), this.redisClient, this.keyQueueProcessing, msg, cause, (err, retryStatus) => {
22
21
  if (err)
23
22
  this.messageHandler.handleError(err);
23
+ else if (!retryStatus)
24
+ this.messageHandler.handleError(new redis_smq_common_1.errors.EmptyCallbackReplyError());
24
25
  else {
25
- this.messageHandler.emit(events_1.events.MESSAGE_UNACKNOWLEDGED, msg, cause);
26
- if (deadLetterCause !== undefined) {
27
- this.messageHandler.emit(events_1.events.MESSAGE_DEAD_LETTERED, msg, deadLetterCause);
26
+ this.messageHandler.emit(events_1.events.MESSAGE_UNACKNOWLEDGED, msg, types_1.EMessageUnacknowledgedCause.CONSUME_ERROR);
27
+ if (retryStatus.status === retry_message_1.ERetryStatus.MESSAGE_DEAD_LETTERED) {
28
+ this.messageHandler.emit(events_1.events.MESSAGE_DEAD_LETTERED, msg);
28
29
  }
29
30
  }
30
31
  });
@@ -45,8 +46,10 @@ class ConsumeMessage {
45
46
  if (this.messageHandler.isRunning() && !isTimeout) {
46
47
  if (timer)
47
48
  clearTimeout(timer);
48
- if (err)
49
- this.unacknowledgeMessage(msg, types_1.EMessageUnacknowledgedCause.UNACKNOWLEDGED, err);
49
+ if (err) {
50
+ this.logger.error(err);
51
+ this.unacknowledgeMessage(msg, types_1.EMessageUnacknowledgedCause.UNACKNOWLEDGED);
52
+ }
50
53
  else {
51
54
  (0, acknowledge_message_1.acknowledgeMessage)(this.messageHandler.getConfig(), this.redisClient, msg, this.keyQueueProcessing, (err) => {
52
55
  if (err)
@@ -60,10 +63,8 @@ class ConsumeMessage {
60
63
  this.messageHandler.getHandler()(message_1.Message.createFromMessage(msg), onConsumed);
61
64
  }
62
65
  catch (error) {
63
- const err = error instanceof Error
64
- ? error
65
- : new consumer_error_1.ConsumerError(`An error occurred while processing message ID (${msg.getRequiredId()})`);
66
- this.unacknowledgeMessage(msg, types_1.EMessageUnacknowledgedCause.CAUGHT_ERROR, err);
66
+ this.logger.error(error);
67
+ this.unacknowledgeMessage(msg, types_1.EMessageUnacknowledgedCause.CONSUME_ERROR);
67
68
  }
68
69
  }
69
70
  handleReceivedMessage(message) {
@@ -1,5 +1,5 @@
1
- import { EMessageDeadLetterCause, EMessageUnacknowledgedCause, IRequiredConfig } from '../../../types';
2
- import { Message } from '../message/message';
1
+ import { EMessageDeadLetterCause, EMessageUnacknowledgedCause, IRequiredConfig } from '../../../../types';
2
+ import { Message } from '../../message/message';
3
3
  import { ICallback, IRedisClientMulti } from 'redis-smq-common/dist/types';
4
4
  import { RedisClient } from 'redis-smq-common';
5
5
  export declare function deadLetterMessage(config: IRequiredConfig, mixed: IRedisClientMulti, message: Message, keyQueueProcessing: string, unacknowledgedCause: EMessageUnacknowledgedCause, deadLetterCause: EMessageDeadLetterCause): void;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.deadLetterMessage = void 0;
4
- const redis_keys_1 = require("../../common/redis-keys/redis-keys");
4
+ const redis_keys_1 = require("../../../common/redis-keys/redis-keys");
5
5
  const redis_smq_common_1 = require("redis-smq-common");
6
6
  function deadLetterMessageTransaction(config, mixed, message, keyQueueProcessing) {
7
7
  const queue = message.getRequiredQueue();
@@ -1,5 +1,5 @@
1
- import { EMessageUnacknowledgedCause } from '../../../types';
2
- import { Message } from '../message/message';
1
+ import { EMessageUnacknowledgedCause } from '../../../../types';
2
+ import { Message } from '../../message/message';
3
3
  import { ICallback, IRedisClientMulti } from 'redis-smq-common/dist/types';
4
4
  import { RedisClient } from 'redis-smq-common';
5
5
  export declare function delayMessageTransaction(mixed: IRedisClientMulti, message: Message, keyQueueProcessing: string): void;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.delayMessage = exports.delayMessageTransaction = void 0;
4
- const redis_keys_1 = require("../../common/redis-keys/redis-keys");
4
+ const redis_keys_1 = require("../../../common/redis-keys/redis-keys");
5
5
  const redis_smq_common_1 = require("redis-smq-common");
6
6
  function delayMessageTransaction(mixed, message, keyQueueProcessing) {
7
7
  const queue = message.getRequiredQueue();
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" />
2
- import { IPlugin, IRequiredConfig, TConsumerMessageHandler, TQueueParams } from '../../../../types';
2
+ import { IEventListener, IRequiredConfig, TConsumerMessageHandler, TQueueParams } from '../../../../types';
3
3
  import { EventEmitter } from 'events';
4
+ import { TCleanUpStatus } from './processing-queue';
4
5
  import { DequeueMessage } from './dequeue-message';
5
6
  import { ConsumeMessage } from './consume-message';
6
7
  import { Consumer } from '../consumer';
@@ -18,10 +19,12 @@ export declare class MessageHandler extends EventEmitter {
18
19
  protected dequeueMessage: DequeueMessage;
19
20
  protected consumeMessage: ConsumeMessage;
20
21
  protected handler: TConsumerMessageHandler;
21
- protected plugins: IPlugin[];
22
+ protected eventListeners: IEventListener[];
22
23
  constructor(consumer: Consumer, queue: TQueueParams, handler: TConsumerMessageHandler, dequeueRedisClient: RedisClient, sharedRedisClient: RedisClient, logger: ICompatibleLogger);
23
24
  protected registerEventsHandlers(): void;
24
- protected initPlugins(): void;
25
+ protected initEventListeners(): void;
26
+ protected cleanUp(cb: ICallback<void>): void;
27
+ protected tearDownEventListeners(cb: ICallback<void>): void;
25
28
  handleError(err: Error): void;
26
29
  dequeue(): void;
27
30
  run(cb: ICallback<void>): void;
@@ -32,5 +35,5 @@ export declare class MessageHandler extends EventEmitter {
32
35
  getConfig(): IRequiredConfig;
33
36
  isRunning(): boolean;
34
37
  getHandler(): TConsumerMessageHandler;
35
- static cleanUp(config: IRequiredConfig, redisClient: RedisClient, consumerId: string, queue: TQueueParams, pendingMulti: IRedisClientMulti | undefined, cb: ICallback<void>): void;
38
+ static cleanUp(config: IRequiredConfig, redisClient: RedisClient, consumerId: string, queue: TQueueParams, pendingMulti: IRedisClientMulti | undefined, cb: ICallback<TCleanUpStatus>): void;
36
39
  }
@@ -8,12 +8,13 @@ const consumer_queues_1 = require("../consumer-queues");
8
8
  const processing_queue_1 = require("./processing-queue");
9
9
  const dequeue_message_1 = require("./dequeue-message");
10
10
  const consume_message_1 = require("./consume-message");
11
- const plugins_1 = require("../../../plugins/plugins");
12
11
  const redis_smq_common_1 = require("redis-smq-common");
12
+ const retry_message_1 = require("./retry-message");
13
+ const event_provider_1 = require("../../../common/event-listeners/event-provider");
13
14
  class MessageHandler extends events_2.EventEmitter {
14
15
  constructor(consumer, queue, handler, dequeueRedisClient, sharedRedisClient, logger) {
15
16
  super();
16
- this.plugins = [];
17
+ this.eventListeners = [];
17
18
  this.id = (0, uuid_1.v4)();
18
19
  this.consumer = consumer;
19
20
  this.consumerId = consumer.getId();
@@ -24,9 +25,9 @@ class MessageHandler extends events_2.EventEmitter {
24
25
  this.powerManager = new redis_smq_common_1.PowerManager();
25
26
  this.logger = logger;
26
27
  this.dequeueMessage = new dequeue_message_1.DequeueMessage(this, dequeueRedisClient);
27
- this.consumeMessage = new consume_message_1.ConsumeMessage(this, dequeueRedisClient);
28
+ this.consumeMessage = new consume_message_1.ConsumeMessage(this, dequeueRedisClient, logger);
28
29
  this.registerEventsHandlers();
29
- this.initPlugins();
30
+ this.initEventListeners();
30
31
  }
31
32
  registerEventsHandlers() {
32
33
  this.on(events_1.events.UP, () => {
@@ -57,10 +58,34 @@ class MessageHandler extends events_2.EventEmitter {
57
58
  });
58
59
  this.on(events_1.events.DOWN, () => this.logger.info('Down.'));
59
60
  }
60
- initPlugins() {
61
- (0, plugins_1.getConsumerPlugins)().forEach((ctor) => {
62
- const plugin = new ctor(this.sharedRedisClient, this.queue, this.consumer);
63
- this.plugins.push(plugin);
61
+ initEventListeners() {
62
+ this.getConfig().eventListeners.consumerEventListeners.forEach((ctor) => {
63
+ const plugin = new ctor(this.sharedRedisClient, this.consumerId, this.queue, new event_provider_1.EventProvider(this));
64
+ this.eventListeners.push(plugin);
65
+ });
66
+ }
67
+ cleanUp(cb) {
68
+ MessageHandler.cleanUp(this.getConfig(), this.sharedRedisClient, this.consumerId, this.queue, undefined, (err, reply) => {
69
+ if (err)
70
+ cb(err);
71
+ else if (reply) {
72
+ this.logger.debug(`Message ID ${reply.message.getId()} has been ${reply.status === retry_message_1.ERetryStatus.MESSAGE_DEAD_LETTERED
73
+ ? 'dead-lettered'
74
+ : 'unacknowledged'}.`);
75
+ cb();
76
+ }
77
+ else
78
+ cb();
79
+ });
80
+ }
81
+ tearDownEventListeners(cb) {
82
+ redis_smq_common_1.async.each(this.eventListeners, (listener, index, done) => listener.quit(done), (err) => {
83
+ if (err)
84
+ cb(err);
85
+ else {
86
+ this.eventListeners = [];
87
+ cb();
88
+ }
64
89
  });
65
90
  }
66
91
  handleError(err) {
@@ -87,25 +112,10 @@ class MessageHandler extends events_2.EventEmitter {
87
112
  const goDown = () => {
88
113
  this.powerManager.goingDown();
89
114
  redis_smq_common_1.async.waterfall([
90
- (cb) => {
91
- this.dequeueMessage.quit(cb);
92
- },
93
- (cb) => {
94
- redis_smq_common_1.async.each(this.plugins, (plugin, index, done) => plugin.quit(done), (err) => {
95
- if (err)
96
- cb(err);
97
- else {
98
- this.plugins = [];
99
- cb();
100
- }
101
- });
102
- },
103
- (cb) => {
104
- MessageHandler.cleanUp(this.getConfig(), this.sharedRedisClient, this.consumerId, this.queue, undefined, cb);
105
- },
106
- (cb) => {
107
- this.dequeueRedisClient.halt(cb);
108
- },
115
+ (cb) => this.dequeueMessage.quit(cb),
116
+ (cb) => this.tearDownEventListeners(cb),
117
+ (cb) => this.cleanUp(cb),
118
+ (cb) => this.dequeueRedisClient.halt(cb),
109
119
  ], (err) => {
110
120
  if (err)
111
121
  cb(err);
@@ -141,9 +151,17 @@ class MessageHandler extends events_2.EventEmitter {
141
151
  }
142
152
  static cleanUp(config, redisClient, consumerId, queue, pendingMulti, cb) {
143
153
  const multi = pendingMulti !== null && pendingMulti !== void 0 ? pendingMulti : redisClient.multi();
154
+ let status = false;
144
155
  redis_smq_common_1.async.waterfall([
145
156
  (cb) => {
146
- processing_queue_1.processingQueue.cleanUpProcessingQueue(config, redisClient, consumerId, queue, multi, cb);
157
+ processing_queue_1.processingQueue.cleanUpProcessingQueue(config, redisClient, consumerId, queue, multi, (err, reply) => {
158
+ if (err)
159
+ cb(err);
160
+ else {
161
+ status = reply !== null && reply !== void 0 ? reply : false;
162
+ cb();
163
+ }
164
+ });
147
165
  },
148
166
  (cb) => {
149
167
  consumer_queues_1.consumerQueues.removeConsumer(multi, queue, consumerId);
@@ -153,9 +171,14 @@ class MessageHandler extends events_2.EventEmitter {
153
171
  if (err)
154
172
  cb(err);
155
173
  else if (pendingMulti)
156
- cb();
174
+ cb(null, status);
157
175
  else
158
- multi.exec((err) => cb(err));
176
+ multi.exec((err) => {
177
+ if (err)
178
+ cb(err);
179
+ else
180
+ cb(null, status);
181
+ });
159
182
  });
160
183
  }
161
184
  }
@@ -22,22 +22,9 @@ class MultiplexedMessageHandler extends message_handler_1.MessageHandler {
22
22
  const goDown = () => {
23
23
  this.powerManager.goingDown();
24
24
  redis_smq_common_1.async.waterfall([
25
- (cb) => {
26
- this.dequeueMessage.quit(cb);
27
- },
28
- (cb) => {
29
- redis_smq_common_1.async.each(this.plugins, (plugin, index, done) => plugin.quit(done), (err) => {
30
- if (err)
31
- cb(err);
32
- else {
33
- this.plugins = [];
34
- cb();
35
- }
36
- });
37
- },
38
- (cb) => {
39
- message_handler_1.MessageHandler.cleanUp(this.getConfig(), this.sharedRedisClient, this.consumerId, this.queue, undefined, cb);
40
- },
25
+ (cb) => this.dequeueMessage.quit(cb),
26
+ (cb) => this.tearDownEventListeners(cb),
27
+ (cb) => this.cleanUp(cb),
41
28
  ], (err) => {
42
29
  if (err)
43
30
  cb(err);