diff --git a/README.md b/README.md
index b1c61614..452138e8 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
> [!IMPORTANT]
-> Currently, RedisSMQ is going under heavy development. Pre-releases at any time may introduce new commits with breaking changes.
+> Currently, RedisSMQ is going under heavy development. Pre-releases at any time may introduce new commits with breaking changes.
> The master branch always reflects the most recent changes. To view the latest release reference see [RedisSMQ v7.2.3](https://github.com/weyoss/redis-smq/tree/v7.2.3)
@@ -17,22 +17,23 @@
-RedisSMQ is a Node.js library for queuing messages (aka jobs) and processing them asynchronously with consumers. Backed by Redis, it allows scaling up your application with ease of use.
+RedisSMQ is a Node.js library for queuing messages (aka jobs) and processing them asynchronously with consumers. Backed by Redis, it allows scaling up your typical applications with ease of use.
## Features
* [High-performance message processing](docs/performance.md).
-* Flexible Producer/Consumer model which offers [Multi-Queue Producers](docs/producing-messages.md) & [Multi-Queue Consumers](docs/consuming-messages.md), focuses on simplicity and without tons of features. This makes RedisSMQ an ideal message broker for microservices-based applications.
-* In case of failures, while delivering or processing a message, RedisSMQ can guaranty that the message is not lost and that it is redelivered [at-least-once](docs/api/classes/ProducibleMessage.md#setretrythreshold). When configured to do so, RedisSMQ can also ensure that the message is delivered [at-most-once](docs/api/classes/ProducibleMessage.md#setretrythreshold).
+* Flexible Producer/Consumer model which offers [Multi-Queue Producers](docs/producing-messages.md) & [Multi-Queue Consumers](docs/consuming-messages.md).
* RedisSMQ offers different exchange types: [Direct Exchange](docs/message-exchanges.md#direct-exchange), [Topic Exchange](docs/message-exchanges.md#topic-exchange), and [FanOut Exchange](docs/message-exchanges.md#fanout-exchange) for publishing a message to one or multiple queues.
-* 3 queuing strategies that you may use depending on your needs and requirements: [FIFO queues, LIFO queues, and Reliable Priority Queues](docs/queues.md).
-* A message can be [set to expire](docs/api/classes/ProducibleMessage.md#setttl) if it has not been delivered within a given amount of time. [Consumption timeout](docs/api/classes/ProducibleMessage.md#setconsumetimeout) allows canceling a message consumption if a consumer did not acknowledge the message for a period of time.
-* [Queue Rate Limiting](docs/queue-rate-limiting.md) which allows to control the rate at which the messages are consumed from a given queue.
-* Builtin [message scheduler](docs/scheduling-messages.md) allowing to delay a message, to deliver a message for N times with an optional period between deliveries, or simply to schedule message delivery using CRON expressions.
-* [Multiplexing](/docs/multiplexing.md): A feature which allows message handlers to use a single redis connection to dequeue and consume messages.
-* An [HTTP interface](https://github.com/weyoss/redis-smq-monitor) is provided to interact with the MQ. RedisSMQ can be managed also from your [web browser](https://github.com/weyoss/redis-smq-monitor-client).
-* Depending on [your preferences](docs/configuration.md), RedisSMQ can use either [node-redis v3](https://github.com/redis/node-redis/tree/v3.1.2), [node-redis v4](https://github.com/redis/node-redis), or [ioredis](https://github.com/luin/ioredis).
-* RedisSMQ is [highly optimized](https://lgtm.com/projects/g/weyoss/redis-smq/context:javascript), implemented using pure callbacks, with small memory footprint and no memory leaks. See [Callback vs Promise vs Async/Await benchmarks](https://gist.github.com/weyoss/24f9ecbda175d943a48cb7ec38bde821).
+* Supports [Point-2-Point](docs/queue-delivery-models.md#point-2-point-delivery-model) and [Pub/Sub](docs/queue-delivery-models.md#pubsub-delivery-model) [delivery models](docs/queue-delivery-models.md).
+* Both [delivery models](docs/queue-delivery-models.md) are reliable. For cases of failure, while delivering/consuming messages, [at-least-once](docs/api/classes/ProducibleMessage.md#setretrythreshold) and [at-most-once](docs/api/classes/ProducibleMessage.md#setretrythreshold) modes may be configured.
+* [3 queuing strategies](docs/queues.md): [FIFO queues](docs/queues.md#fifo-first-in-first-out-queues), [LIFO queues](docs/queues.md#lifo-last-in-first-out-queues), and [Reliable Priority Queues](docs/queues.md#priority-queues).
+* Messages can be [set to expire](docs/api/classes/ProducibleMessage.md#setttl) when not delivered within a given amount of time or to have a [consumption timeout](docs/api/classes/ProducibleMessage.md#setconsumetimeout) while being in process.
+* Queues may be [rate Limited](docs/queue-rate-limiting.md) to control the rate at which the messages are consumed.
+* Has a builtin [scheduler](docs/scheduling-messages.md) allowing messages [to be delayed](docs/api/classes/ProducibleMessage.md#setscheduleddelay), [to be delivered for N times](docs/api/classes/ProducibleMessage.md#setscheduledrepeat) with an optional [period between deliveries](docs/api/classes/ProducibleMessage.md#setscheduledrepeatperiod), or simply [to be scheduled using CRON expressions](docs/api/classes/ProducibleMessage.md#setscheduledcron).
+* Provides [an HTTP API](https://github.com/weyoss/redis-smq-monitor) to interact with the message queue for external services.
+* RedisSMQ can be managed also from your [web browser](https://github.com/weyoss/redis-smq-monitor-client).
+* Either [node-redis](https://github.com/redis/node-redis) or [ioredis](https://github.com/luin/ioredis) can be used as a Redis client.
+* [Highly optimized](https://lgtm.com/projects/g/weyoss/redis-smq/context:javascript), implemented using pure callbacks, with small memory footprint and no memory leaks. See [Callback vs Promise vs Async/Await benchmarks](https://gist.github.com/weyoss/24f9ecbda175d943a48cb7ec38bde821).
* [Both ESM & CJS modules are supported](docs/esm-cjs-modules.md).
## RedisSMQ Use Case: Multi-Queue Producers & Multi-Queue Consumers
@@ -65,14 +66,16 @@ A queue is responsible for holding messages which are produced by producers and
### Creating a queue
```javascript
-const { Queue, EQueueType } = require('redis-smq');
+const { Queue, EQueueType, EQueueDeliveryModel } = require('redis-smq');
const queue = new Queue();
// Creating a LIFO queue
-queue.save('my_queue', EQueueType.LIFO_QUEUE, (err) => console.log(err));
+queue.save('my_queue', EQueueType.LIFO_QUEUE, EQueueDeliveryModel.POINT_TO_POINT, (err) => console.log(err));
```
+In the example above we are defining a [LIFO queue](docs/queues.md#lifo-last-in-first-out-queues) with a [POINT-2-POINT delivery model](docs/queue-delivery-models.md#point-2-point-delivery-model).
+
### Producing a message
```javascript
diff --git a/docs/README.md b/docs/README.md
index 0bab43c0..cd6bc417 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -10,11 +10,13 @@ See [API Reference](api/README.md) for more details.
- [Configuration](configuration.md)
- [Queues](queues.md)
+- [Queue Delivery Models](queue-delivery-models.md)
- [Producing Messages](producing-messages.md)
- [Consuming Messages](consuming-messages.md)
- [Messages](messages.md)
- [Message Exchanges](message-exchanges.md)
- [Queue Rate Limiting](queue-rate-limiting.md)
+- [Exchanges and Delivery Models](exchanges-and-delivery-models.md)
- [Multiplexing](multiplexing.md)
- [Scheduling Messages](scheduling-messages.md)
- [Performance](performance.md)
diff --git a/docs/api/README.md b/docs/api/README.md
index 30827ece..cb279fcb 100644
--- a/docs/api/README.md
+++ b/docs/api/README.md
@@ -12,6 +12,7 @@
- [EMessagePriority](enums/EMessagePriority.md)
- [EMessageProperty](enums/EMessageProperty.md)
- [EMessagePropertyStatus](enums/EMessagePropertyStatus.md)
+- [EQueueDeliveryModel](enums/EQueueDeliveryModel.md)
- [EQueueProperty](enums/EQueueProperty.md)
- [EQueueType](enums/EQueueType.md)
@@ -19,8 +20,7 @@
- [Configuration](classes/Configuration.md)
- [Consumer](classes/Consumer.md)
-- [ExchangeDirect](classes/ExchangeDirect.md)
-- [ExchangeFanOut](classes/ExchangeFanOut.md)
+- [ConsumerGroups](classes/ConsumerGroups.md)
- [ExchangeTopic](classes/ExchangeTopic.md)
- [Message](classes/Message.md)
- [Namespace](classes/Namespace.md)
@@ -34,13 +34,20 @@
- [QueueRateLimit](classes/QueueRateLimit.md)
- [QueueScheduledMessages](classes/QueueScheduledMessages.md)
-### Errors
+## Errors
- [ConsumerError](classes/ConsumerError.md)
+- [ConsumerGroupDeleteError](classes/ConsumerGroupDeleteError.md)
+- [ConsumerGroupIdNotFoundError](classes/ConsumerGroupIdNotFoundError.md)
+- [ConsumerGroupIdNotSupportedError](classes/ConsumerGroupIdNotSupportedError.md)
+- [ConsumerGroupIdRequiredError](classes/ConsumerGroupIdRequiredError.md)
+- [ConsumerInvalidGroupIdError](classes/ConsumerInvalidGroupIdError.md)
- [ConsumerMessageHandlerAlreadyExistsError](classes/ConsumerMessageHandlerAlreadyExistsError.md)
+- [ExchangeDirect](classes/ExchangeDirect.md)
+- [ExchangeError](classes/ExchangeError.md)
+- [ExchangeFanOut](classes/ExchangeFanOut.md)
- [ExchangeFanOutError](classes/ExchangeFanOutError.md)
- [ExchangeInvalidDataError](classes/ExchangeInvalidDataError.md)
-- [ExchangeError](classes/ExchangeError.md)
- [MessageDeleteError](classes/MessageDeleteError.md)
- [MessageDestinationQueueAlreadySetError](classes/MessageDestinationQueueAlreadySetError.md)
- [MessageDestinationQueueRequiredError](classes/MessageDestinationQueueRequiredError.md)
@@ -49,16 +56,18 @@
- [MessageNotFoundError](classes/MessageNotFoundError.md)
- [ProducerError](classes/ProducerError.md)
- [ProducerInstanceNotRunningError](classes/ProducerInstanceNotRunningError.md)
+- [ProducerMessageExchangeRequiredError](classes/ProducerMessageExchangeRequiredError.md)
- [ProducerMessageNotPublishedError](classes/ProducerMessageNotPublishedError.md)
- [ProducerMessageNotScheduledError](classes/ProducerMessageNotScheduledError.md)
-- [QueueRateLimitError](classes/QueueRateLimitError.md)
-- [QueueNamespaceNotFoundError](classes/QueueNamespaceNotFoundError.md)
-- [QueueNotEmptyError](classes/QueueNotEmptyError.md)
-- [QueueNotFoundError](classes/QueueNotFoundError.md)
+- [ProducerQueueWithoutConsumerGroupsError](classes/ProducerQueueWithoutConsumerGroupsError.md)
- [QueueError](classes/QueueError.md)
- [QueueExistsError](classes/QueueExistsError.md)
- [QueueHasRunningConsumersError](classes/QueueHasRunningConsumersError.md)
- [QueueMessageRequeueError](classes/QueueMessageRequeueError.md)
+- [QueueNamespaceNotFoundError](classes/QueueNamespaceNotFoundError.md)
+- [QueueNotEmptyError](classes/QueueNotEmptyError.md)
+- [QueueNotFoundError](classes/QueueNotFoundError.md)
+- [QueueRateLimitError](classes/QueueRateLimitError.md)
### Interfaces
@@ -76,10 +85,14 @@
- [IMessagesConfigStorageOptions](interfaces/IMessagesConfigStorageOptions.md)
- [IMessagesConfigStorageOptionsRequired](interfaces/IMessagesConfigStorageOptionsRequired.md)
- [IMessagesConfigStorageRequired](interfaces/IMessagesConfigStorageRequired.md)
+- [IQueueConsumerGroupParams](interfaces/IQueueConsumerGroupParams.md)
+- [IQueueGroupConsumersPendingCount](interfaces/IQueueGroupConsumersPendingCount.md)
- [IQueueMessages](interfaces/IQueueMessages.md)
- [IQueueMessagesCount](interfaces/IQueueMessagesCount.md)
- [IQueueMessagesPage](interfaces/IQueueMessagesPage.md)
+- [IQueueMessagesRequeuable](interfaces/IQueueMessagesRequeuable.md)
- [IQueueParams](interfaces/IQueueParams.md)
+- [IQueueParsedParams](interfaces/IQueueParsedParams.md)
- [IQueueProperties](interfaces/IQueueProperties.md)
- [IQueueRateLimit](interfaces/IQueueRateLimit.md)
- [IRedisSMQConfig](interfaces/IRedisSMQConfig.md)
@@ -92,18 +105,15 @@
- [TConsumerRedisKeys](README.md#tconsumerrediskeys)
- [TEventListenersConfig](README.md#teventlistenersconfig)
- [TExchange](README.md#texchange)
-- [TExchangeDirect](README.md#texchangedirect)
- [TExchangeDirectBindingParams](README.md#texchangedirectbindingparams)
-- [TExchangeDirectSerialized](README.md#texchangedirectserialized)
-- [TExchangeFanOut](README.md#texchangefanout)
- [TExchangeFanOutBindingParams](README.md#texchangefanoutbindingparams)
-- [TExchangeFanOutSerialized](README.md#texchangefanoutserialized)
- [TExchangeSerialized](README.md#texchangeserialized)
-- [TExchangeTopic](README.md#texchangetopic)
- [TExchangeTopicBindingParams](README.md#texchangetopicbindingparams)
-- [TExchangeTopicSerialized](README.md#texchangetopicserialized)
- [TMessageConsumeOptions](README.md#tmessageconsumeoptions)
- [TQueueConsumer](README.md#tqueueconsumer)
+- [TQueueExtendedParams](README.md#tqueueextendedparams)
+- [TQueueMessagesPaginationParams](README.md#tqueuemessagespaginationparams)
+- [TQueueMessagesParams](README.md#tqueuemessagesparams)
- [TRedisSMQEvent](README.md#tredissmqevent)
- [TTopicParams](README.md#ttopicparams)
@@ -163,13 +173,7 @@ ___
### TExchange
-Ƭ **TExchange**: [`TExchangeDirect`](README.md#texchangedirect) \| [`TExchangeTopic`](README.md#texchangetopic) \| [`TExchangeFanOut`](README.md#texchangefanout)
-
-___
-
-### TExchangeDirect
-
-Ƭ **TExchangeDirect**: [`IExchange`](interfaces/IExchange.md)\<[`TExchangeDirectBindingParams`](README.md#texchangedirectbindingparams), [`DIRECT`](enums/EExchangeType.md#direct)\>
+Ƭ **TExchange**: [`ExchangeDirect`](classes/ExchangeDirect.md) \| [`ExchangeTopic`](classes/ExchangeTopic.md) \| [`ExchangeFanOut`](classes/ExchangeFanOut.md)
___
@@ -179,39 +183,15 @@ ___
___
-### TExchangeDirectSerialized
-
-Ƭ **TExchangeDirectSerialized**: [`IExchangeSerialized`](interfaces/IExchangeSerialized.md)\<[`TExchangeDirectBindingParams`](README.md#texchangedirectbindingparams), [`DIRECT`](enums/EExchangeType.md#direct)\>
-
-___
-
-### TExchangeFanOut
-
-Ƭ **TExchangeFanOut**: [`IExchange`](interfaces/IExchange.md)\<[`TExchangeFanOutBindingParams`](README.md#texchangefanoutbindingparams), [`FANOUT`](enums/EExchangeType.md#fanout)\>
-
-___
-
### TExchangeFanOutBindingParams
Ƭ **TExchangeFanOutBindingParams**: `string`
___
-### TExchangeFanOutSerialized
-
-Ƭ **TExchangeFanOutSerialized**: [`IExchangeSerialized`](interfaces/IExchangeSerialized.md)\<[`TExchangeFanOutBindingParams`](README.md#texchangefanoutbindingparams), [`FANOUT`](enums/EExchangeType.md#fanout)\>
-
-___
-
### TExchangeSerialized
-Ƭ **TExchangeSerialized**: [`TExchangeDirectSerialized`](README.md#texchangedirectserialized) \| [`TExchangeTopicSerialized`](README.md#texchangetopicserialized) \| [`TExchangeFanOutSerialized`](README.md#texchangefanoutserialized)
-
-___
-
-### TExchangeTopic
-
-Ƭ **TExchangeTopic**: [`IExchange`](interfaces/IExchange.md)\<[`TExchangeTopicBindingParams`](README.md#texchangetopicbindingparams), [`TOPIC`](enums/EExchangeType.md#topic)\>
+Ƭ **TExchangeSerialized**: `ReturnType`\<[`ExchangeDirect`](classes/ExchangeDirect.md)[``"toJSON"``]\> \| `ReturnType`\<[`ExchangeTopic`](classes/ExchangeTopic.md)[``"toJSON"``]\> \| `ReturnType`\<[`ExchangeFanOut`](classes/ExchangeFanOut.md)[``"toJSON"``]\>
___
@@ -221,12 +201,6 @@ ___
___
-### TExchangeTopicSerialized
-
-Ƭ **TExchangeTopicSerialized**: [`IExchangeSerialized`](interfaces/IExchangeSerialized.md)\<[`TExchangeTopicBindingParams`](README.md#texchangetopicbindingparams), [`TOPIC`](enums/EExchangeType.md#topic)\>
-
-___
-
### TMessageConsumeOptions
Ƭ **TMessageConsumeOptions**: `Object`
@@ -257,6 +231,40 @@ ___
___
+### TQueueExtendedParams
+
+Ƭ **TQueueExtendedParams**: `string` \| [`IQueueParams`](interfaces/IQueueParams.md) \| [`IQueueConsumerGroupParams`](interfaces/IQueueConsumerGroupParams.md)
+
+___
+
+### TQueueMessagesPaginationParams
+
+Ƭ **TQueueMessagesPaginationParams**: `Object`
+
+#### Type declaration
+
+| Name | Type |
+| :------ | :------ |
+| `consumerGroupId?` | `string` \| ``null`` |
+| `page` | `number` |
+| `pageSize` | `number` |
+| `queue` | `string` \| [`IQueueParams`](interfaces/IQueueParams.md) |
+
+___
+
+### TQueueMessagesParams
+
+Ƭ **TQueueMessagesParams**: `Object`
+
+#### Type declaration
+
+| Name | Type |
+| :------ | :------ |
+| `consumerGroupId?` | `string` \| ``null`` |
+| `queue` | `string` \| [`IQueueParams`](interfaces/IQueueParams.md) |
+
+___
+
### TRedisSMQEvent
- [`TEvent`](https://github.com/weyoss/redis-smq-common/blob/master/docs/api/README.md#tevent)
diff --git a/docs/api/classes/Consumer.md b/docs/api/classes/Consumer.md
index 4111bc5e..cc025922 100644
--- a/docs/api/classes/Consumer.md
+++ b/docs/api/classes/Consumer.md
@@ -59,7 +59,7 @@ Base.constructor
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`void`\> |
#### Returns
@@ -76,7 +76,7 @@ ___
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `messageHandler` | [`TConsumerMessageHandler`](../README.md#tconsumermessagehandler) |
| `cb` | `ICallback`\<`void`\> |
@@ -102,11 +102,11 @@ ___
### getQueues
-▸ **getQueues**(): [`IQueueParams`](../interfaces/IQueueParams.md)[]
+▸ **getQueues**(): [`IQueueParsedParams`](../interfaces/IQueueParsedParams.md)[]
#### Returns
-[`IQueueParams`](../interfaces/IQueueParams.md)[]
+[`IQueueParsedParams`](../interfaces/IQueueParsedParams.md)[]
___
diff --git a/docs/api/classes/ConsumerError.md b/docs/api/classes/ConsumerError.md
index e1a9eef9..3485c93e 100644
--- a/docs/api/classes/ConsumerError.md
+++ b/docs/api/classes/ConsumerError.md
@@ -10,6 +10,16 @@
↳↳ [`ConsumerMessageHandlerAlreadyExistsError`](ConsumerMessageHandlerAlreadyExistsError.md)
+ ↳↳ [`ConsumerGroupDeleteError`](ConsumerGroupDeleteError.md)
+
+ ↳↳ [`ConsumerGroupIdNotFoundError`](ConsumerGroupIdNotFoundError.md)
+
+ ↳↳ [`ConsumerGroupIdNotSupportedError`](ConsumerGroupIdNotSupportedError.md)
+
+ ↳↳ [`ConsumerGroupIdRequiredError`](ConsumerGroupIdRequiredError.md)
+
+ ↳↳ [`ConsumerInvalidGroupIdError`](ConsumerInvalidGroupIdError.md)
+
## Table of contents
### Constructors
diff --git a/docs/api/classes/ConsumerGroupDeleteError.md b/docs/api/classes/ConsumerGroupDeleteError.md
new file mode 100644
index 00000000..47232c24
--- /dev/null
+++ b/docs/api/classes/ConsumerGroupDeleteError.md
@@ -0,0 +1,35 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / ConsumerGroupDeleteError
+
+# Class: ConsumerGroupDeleteError
+
+## Hierarchy
+
+- [`ConsumerError`](ConsumerError.md)
+
+ ↳ **`ConsumerGroupDeleteError`**
+
+## Table of contents
+
+### Constructors
+
+- [constructor](ConsumerGroupDeleteError.md#constructor)
+
+## Constructors
+
+### constructor
+
+• **new ConsumerGroupDeleteError**(`message?`): [`ConsumerGroupDeleteError`](ConsumerGroupDeleteError.md)
+
+#### Parameters
+
+| Name | Type |
+| :------ | :------ |
+| `message?` | `string` |
+
+#### Returns
+
+[`ConsumerGroupDeleteError`](ConsumerGroupDeleteError.md)
+
+#### Inherited from
+
+[ConsumerError](ConsumerError.md).[constructor](ConsumerError.md#constructor)
diff --git a/docs/api/classes/ConsumerGroupIdNotFoundError.md b/docs/api/classes/ConsumerGroupIdNotFoundError.md
new file mode 100644
index 00000000..b18d3a80
--- /dev/null
+++ b/docs/api/classes/ConsumerGroupIdNotFoundError.md
@@ -0,0 +1,29 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / ConsumerGroupIdNotFoundError
+
+# Class: ConsumerGroupIdNotFoundError
+
+## Hierarchy
+
+- [`ConsumerError`](ConsumerError.md)
+
+ ↳ **`ConsumerGroupIdNotFoundError`**
+
+## Table of contents
+
+### Constructors
+
+- [constructor](ConsumerGroupIdNotFoundError.md#constructor)
+
+## Constructors
+
+### constructor
+
+• **new ConsumerGroupIdNotFoundError**(): [`ConsumerGroupIdNotFoundError`](ConsumerGroupIdNotFoundError.md)
+
+#### Returns
+
+[`ConsumerGroupIdNotFoundError`](ConsumerGroupIdNotFoundError.md)
+
+#### Overrides
+
+[ConsumerError](ConsumerError.md).[constructor](ConsumerError.md#constructor)
diff --git a/docs/api/classes/ConsumerGroupIdNotSupportedError.md b/docs/api/classes/ConsumerGroupIdNotSupportedError.md
new file mode 100644
index 00000000..f8023347
--- /dev/null
+++ b/docs/api/classes/ConsumerGroupIdNotSupportedError.md
@@ -0,0 +1,29 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / ConsumerGroupIdNotSupportedError
+
+# Class: ConsumerGroupIdNotSupportedError
+
+## Hierarchy
+
+- [`ConsumerError`](ConsumerError.md)
+
+ ↳ **`ConsumerGroupIdNotSupportedError`**
+
+## Table of contents
+
+### Constructors
+
+- [constructor](ConsumerGroupIdNotSupportedError.md#constructor)
+
+## Constructors
+
+### constructor
+
+• **new ConsumerGroupIdNotSupportedError**(): [`ConsumerGroupIdNotSupportedError`](ConsumerGroupIdNotSupportedError.md)
+
+#### Returns
+
+[`ConsumerGroupIdNotSupportedError`](ConsumerGroupIdNotSupportedError.md)
+
+#### Overrides
+
+[ConsumerError](ConsumerError.md).[constructor](ConsumerError.md#constructor)
diff --git a/docs/api/classes/ConsumerGroupIdRequiredError.md b/docs/api/classes/ConsumerGroupIdRequiredError.md
new file mode 100644
index 00000000..4c2100d6
--- /dev/null
+++ b/docs/api/classes/ConsumerGroupIdRequiredError.md
@@ -0,0 +1,29 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / ConsumerGroupIdRequiredError
+
+# Class: ConsumerGroupIdRequiredError
+
+## Hierarchy
+
+- [`ConsumerError`](ConsumerError.md)
+
+ ↳ **`ConsumerGroupIdRequiredError`**
+
+## Table of contents
+
+### Constructors
+
+- [constructor](ConsumerGroupIdRequiredError.md#constructor)
+
+## Constructors
+
+### constructor
+
+• **new ConsumerGroupIdRequiredError**(): [`ConsumerGroupIdRequiredError`](ConsumerGroupIdRequiredError.md)
+
+#### Returns
+
+[`ConsumerGroupIdRequiredError`](ConsumerGroupIdRequiredError.md)
+
+#### Overrides
+
+[ConsumerError](ConsumerError.md).[constructor](ConsumerError.md#constructor)
diff --git a/docs/api/classes/ConsumerGroups.md b/docs/api/classes/ConsumerGroups.md
new file mode 100644
index 00000000..8f1ccde1
--- /dev/null
+++ b/docs/api/classes/ConsumerGroups.md
@@ -0,0 +1,78 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / ConsumerGroups
+
+# Class: ConsumerGroups
+
+## Table of contents
+
+### Constructors
+
+- [constructor](ConsumerGroups.md#constructor)
+
+### Methods
+
+- [deleteConsumerGroup](ConsumerGroups.md#deleteconsumergroup)
+- [getConsumerGroups](ConsumerGroups.md#getconsumergroups)
+- [saveConsumerGroup](ConsumerGroups.md#saveconsumergroup)
+
+## Constructors
+
+### constructor
+
+• **new ConsumerGroups**(): [`ConsumerGroups`](ConsumerGroups.md)
+
+#### Returns
+
+[`ConsumerGroups`](ConsumerGroups.md)
+
+## Methods
+
+### deleteConsumerGroup
+
+▸ **deleteConsumerGroup**(`queue`, `groupId`, `cb`): `void`
+
+#### Parameters
+
+| Name | Type |
+| :------ | :------ |
+| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `groupId` | `string` |
+| `cb` | `ICallback`\<`void`\> |
+
+#### Returns
+
+`void`
+
+___
+
+### getConsumerGroups
+
+▸ **getConsumerGroups**(`queue`, `cb`): `void`
+
+#### Parameters
+
+| Name | Type |
+| :------ | :------ |
+| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `cb` | `ICallback`\<`string`[]\> |
+
+#### Returns
+
+`void`
+
+___
+
+### saveConsumerGroup
+
+▸ **saveConsumerGroup**(`queue`, `groupId`, `cb`): `void`
+
+#### Parameters
+
+| Name | Type |
+| :------ | :------ |
+| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `groupId` | `string` |
+| `cb` | `ICallback`\<`number`\> |
+
+#### Returns
+
+`void`
diff --git a/docs/api/classes/ConsumerInvalidGroupIdError.md b/docs/api/classes/ConsumerInvalidGroupIdError.md
new file mode 100644
index 00000000..60f0fd1e
--- /dev/null
+++ b/docs/api/classes/ConsumerInvalidGroupIdError.md
@@ -0,0 +1,29 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / ConsumerInvalidGroupIdError
+
+# Class: ConsumerInvalidGroupIdError
+
+## Hierarchy
+
+- [`ConsumerError`](ConsumerError.md)
+
+ ↳ **`ConsumerInvalidGroupIdError`**
+
+## Table of contents
+
+### Constructors
+
+- [constructor](ConsumerInvalidGroupIdError.md#constructor)
+
+## Constructors
+
+### constructor
+
+• **new ConsumerInvalidGroupIdError**(): [`ConsumerInvalidGroupIdError`](ConsumerInvalidGroupIdError.md)
+
+#### Returns
+
+[`ConsumerInvalidGroupIdError`](ConsumerInvalidGroupIdError.md)
+
+#### Overrides
+
+[ConsumerError](ConsumerError.md).[constructor](ConsumerError.md#constructor)
diff --git a/docs/api/classes/ConsumerMessageHandlerAlreadyExistsError.md b/docs/api/classes/ConsumerMessageHandlerAlreadyExistsError.md
index 934789a6..3e6ff709 100644
--- a/docs/api/classes/ConsumerMessageHandlerAlreadyExistsError.md
+++ b/docs/api/classes/ConsumerMessageHandlerAlreadyExistsError.md
@@ -24,7 +24,7 @@
| Name | Type |
| :------ | :------ |
-| `queue` | [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`IQueueParsedParams`](../interfaces/IQueueParsedParams.md) |
#### Returns
diff --git a/docs/api/classes/ProducerError.md b/docs/api/classes/ProducerError.md
index caf74ebf..de534b8a 100644
--- a/docs/api/classes/ProducerError.md
+++ b/docs/api/classes/ProducerError.md
@@ -14,6 +14,10 @@
↳↳ [`ProducerInstanceNotRunningError`](ProducerInstanceNotRunningError.md)
+ ↳↳ [`ProducerQueueWithoutConsumerGroupsError`](ProducerQueueWithoutConsumerGroupsError.md)
+
+ ↳↳ [`ProducerMessageExchangeRequiredError`](ProducerMessageExchangeRequiredError.md)
+
## Table of contents
### Constructors
diff --git a/docs/api/classes/ProducerMessageExchangeRequiredError.md b/docs/api/classes/ProducerMessageExchangeRequiredError.md
new file mode 100644
index 00000000..04b31381
--- /dev/null
+++ b/docs/api/classes/ProducerMessageExchangeRequiredError.md
@@ -0,0 +1,35 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / ProducerMessageExchangeRequiredError
+
+# Class: ProducerMessageExchangeRequiredError
+
+## Hierarchy
+
+- [`ProducerError`](ProducerError.md)
+
+ ↳ **`ProducerMessageExchangeRequiredError`**
+
+## Table of contents
+
+### Constructors
+
+- [constructor](ProducerMessageExchangeRequiredError.md#constructor)
+
+## Constructors
+
+### constructor
+
+• **new ProducerMessageExchangeRequiredError**(`message?`): [`ProducerMessageExchangeRequiredError`](ProducerMessageExchangeRequiredError.md)
+
+#### Parameters
+
+| Name | Type |
+| :------ | :------ |
+| `message?` | `string` |
+
+#### Returns
+
+[`ProducerMessageExchangeRequiredError`](ProducerMessageExchangeRequiredError.md)
+
+#### Inherited from
+
+[ProducerError](ProducerError.md).[constructor](ProducerError.md#constructor)
diff --git a/docs/api/classes/ProducerQueueWithoutConsumerGroupsError.md b/docs/api/classes/ProducerQueueWithoutConsumerGroupsError.md
new file mode 100644
index 00000000..52245f12
--- /dev/null
+++ b/docs/api/classes/ProducerQueueWithoutConsumerGroupsError.md
@@ -0,0 +1,35 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / ProducerQueueWithoutConsumerGroupsError
+
+# Class: ProducerQueueWithoutConsumerGroupsError
+
+## Hierarchy
+
+- [`ProducerError`](ProducerError.md)
+
+ ↳ **`ProducerQueueWithoutConsumerGroupsError`**
+
+## Table of contents
+
+### Constructors
+
+- [constructor](ProducerQueueWithoutConsumerGroupsError.md#constructor)
+
+## Constructors
+
+### constructor
+
+• **new ProducerQueueWithoutConsumerGroupsError**(`message?`): [`ProducerQueueWithoutConsumerGroupsError`](ProducerQueueWithoutConsumerGroupsError.md)
+
+#### Parameters
+
+| Name | Type |
+| :------ | :------ |
+| `message?` | `string` |
+
+#### Returns
+
+[`ProducerQueueWithoutConsumerGroupsError`](ProducerQueueWithoutConsumerGroupsError.md)
+
+#### Inherited from
+
+[ProducerError](ProducerError.md).[constructor](ProducerError.md#constructor)
diff --git a/docs/api/classes/Queue.md b/docs/api/classes/Queue.md
index c175b673..8bdfa3ec 100644
--- a/docs/api/classes/Queue.md
+++ b/docs/api/classes/Queue.md
@@ -97,7 +97,7 @@ ___
### save
-▸ **save**(`queue`, `queueType`, `cb`): `void`
+▸ **save**(`queue`, `queueType`, `deliveryModel`, `cb`): `void`
#### Parameters
@@ -105,6 +105,7 @@ ___
| :------ | :------ |
| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
| `queueType` | [`EQueueType`](../enums/EQueueType.md) |
+| `deliveryModel` | [`EQueueDeliveryModel`](../enums/EQueueDeliveryModel.md) |
| `cb` | `ICallback`\<\{ `properties`: [`IQueueProperties`](../interfaces/IQueueProperties.md) ; `queue`: [`IQueueParams`](../interfaces/IQueueParams.md) }\> |
#### Returns
diff --git a/docs/api/classes/QueueAcknowledgedMessages.md b/docs/api/classes/QueueAcknowledgedMessages.md
index c8aadbfa..2b743fb0 100644
--- a/docs/api/classes/QueueAcknowledgedMessages.md
+++ b/docs/api/classes/QueueAcknowledgedMessages.md
@@ -8,6 +8,10 @@
↳ **`QueueAcknowledgedMessages`**
+## Implements
+
+- [`IQueueMessagesRequeuable`](../interfaces/IQueueMessagesRequeuable.md)
+
## Table of contents
### Constructors
@@ -45,7 +49,7 @@ QueueMessagesPaginatorList.constructor
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`number`\> |
#### Returns
@@ -60,14 +64,14 @@ ___
### getMessages
-▸ **getMessages**(`queue`, `cursor`, `pageSize`, `cb`): `void`
+▸ **getMessages**(`queue`, `page`, `pageSize`, `cb`): `void`
#### Parameters
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
-| `cursor` | `number` |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
+| `page` | `number` |
| `pageSize` | `number` |
| `cb` | `ICallback`\<[`IQueueMessagesPage`](../interfaces/IQueueMessagesPage.md)\<[`IConsumableMessage`](../interfaces/IConsumableMessage.md)\>\> |
@@ -89,7 +93,7 @@ ___
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`void`\> |
#### Returns
@@ -104,20 +108,20 @@ ___
### requeueMessage
-▸ **requeueMessage**(`source`, `id`, `cb`): `void`
+▸ **requeueMessage**(`queue`, `messageId`, `cb`): `void`
#### Parameters
| Name | Type |
| :------ | :------ |
-| `source` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
-| `id` | `string` |
+| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `messageId` | `string` |
| `cb` | `ICallback`\<`void`\> |
#### Returns
`void`
-#### Inherited from
+#### Implementation of
-QueueMessagesPaginatorList.requeueMessage
+[IQueueMessagesRequeuable](../interfaces/IQueueMessagesRequeuable.md).[requeueMessage](../interfaces/IQueueMessagesRequeuable.md#requeuemessage)
diff --git a/docs/api/classes/QueueDeadLetteredMessages.md b/docs/api/classes/QueueDeadLetteredMessages.md
index 2e728bf8..f081f1c1 100644
--- a/docs/api/classes/QueueDeadLetteredMessages.md
+++ b/docs/api/classes/QueueDeadLetteredMessages.md
@@ -8,6 +8,10 @@
↳ **`QueueDeadLetteredMessages`**
+## Implements
+
+- [`IQueueMessagesRequeuable`](../interfaces/IQueueMessagesRequeuable.md)
+
## Table of contents
### Constructors
@@ -45,7 +49,7 @@ QueueMessagesPaginatorList.constructor
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`number`\> |
#### Returns
@@ -60,14 +64,14 @@ ___
### getMessages
-▸ **getMessages**(`queue`, `cursor`, `pageSize`, `cb`): `void`
+▸ **getMessages**(`queue`, `page`, `pageSize`, `cb`): `void`
#### Parameters
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
-| `cursor` | `number` |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
+| `page` | `number` |
| `pageSize` | `number` |
| `cb` | `ICallback`\<[`IQueueMessagesPage`](../interfaces/IQueueMessagesPage.md)\<[`IConsumableMessage`](../interfaces/IConsumableMessage.md)\>\> |
@@ -89,7 +93,7 @@ ___
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`void`\> |
#### Returns
@@ -104,20 +108,20 @@ ___
### requeueMessage
-▸ **requeueMessage**(`source`, `id`, `cb`): `void`
+▸ **requeueMessage**(`queue`, `messageId`, `cb`): `void`
#### Parameters
| Name | Type |
| :------ | :------ |
-| `source` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
-| `id` | `string` |
+| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `messageId` | `string` |
| `cb` | `ICallback`\<`void`\> |
#### Returns
`void`
-#### Inherited from
+#### Implementation of
-QueueMessagesPaginatorList.requeueMessage
+[IQueueMessagesRequeuable](../interfaces/IQueueMessagesRequeuable.md).[requeueMessage](../interfaces/IQueueMessagesRequeuable.md#requeuemessage)
diff --git a/docs/api/classes/QueueMessageRequeueError.md b/docs/api/classes/QueueMessageRequeueError.md
index d6baa01c..f320ad96 100644
--- a/docs/api/classes/QueueMessageRequeueError.md
+++ b/docs/api/classes/QueueMessageRequeueError.md
@@ -18,7 +18,13 @@
### constructor
-• **new QueueMessageRequeueError**(): [`QueueMessageRequeueError`](QueueMessageRequeueError.md)
+• **new QueueMessageRequeueError**(`msg?`): [`QueueMessageRequeueError`](QueueMessageRequeueError.md)
+
+#### Parameters
+
+| Name | Type | Default value |
+| :------ | :------ | :------ |
+| `msg` | `string` | `'MESSAGE_REQUEUE_ERROR'` |
#### Returns
diff --git a/docs/api/classes/QueueMessages.md b/docs/api/classes/QueueMessages.md
index 70388af1..e23add3f 100644
--- a/docs/api/classes/QueueMessages.md
+++ b/docs/api/classes/QueueMessages.md
@@ -45,7 +45,7 @@ QueueMessagesPaginatorSet.constructor
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`number`\> |
#### Returns
@@ -77,14 +77,14 @@ ___
### getMessages
-▸ **getMessages**(`queue`, `cursor`, `pageSize`, `cb`): `void`
+▸ **getMessages**(`queue`, `page`, `pageSize`, `cb`): `void`
#### Parameters
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
-| `cursor` | `number` |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
+| `page` | `number` |
| `pageSize` | `number` |
| `cb` | `ICallback`\<[`IQueueMessagesPage`](../interfaces/IQueueMessagesPage.md)\<[`IConsumableMessage`](../interfaces/IConsumableMessage.md)\>\> |
@@ -106,7 +106,7 @@ ___
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`void`\> |
#### Returns
diff --git a/docs/api/classes/QueuePendingMessages.md b/docs/api/classes/QueuePendingMessages.md
index 035d64ba..439648e3 100644
--- a/docs/api/classes/QueuePendingMessages.md
+++ b/docs/api/classes/QueuePendingMessages.md
@@ -38,7 +38,7 @@
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`number`\> |
#### Returns
@@ -53,14 +53,14 @@ ___
### getMessages
-▸ **getMessages**(`queue`, `cursor`, `pageSize`, `cb`): `void`
+▸ **getMessages**(`queue`, `page`, `pageSize`, `cb`): `void`
#### Parameters
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
-| `cursor` | `number` |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
+| `page` | `number` |
| `pageSize` | `number` |
| `cb` | `ICallback`\<[`IQueueMessagesPage`](../interfaces/IQueueMessagesPage.md)\<[`IConsumableMessage`](../interfaces/IConsumableMessage.md)\>\> |
@@ -82,7 +82,7 @@ ___
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`void`\> |
#### Returns
diff --git a/docs/api/classes/QueueRateLimit.md b/docs/api/classes/QueueRateLimit.md
index b6d45f06..bd31a03b 100644
--- a/docs/api/classes/QueueRateLimit.md
+++ b/docs/api/classes/QueueRateLimit.md
@@ -14,7 +14,6 @@
- [get](QueueRateLimit.md#get)
- [hasExceeded](QueueRateLimit.md#hasexceeded)
- [set](QueueRateLimit.md#set)
-- [hasExceeded](QueueRateLimit.md#hasexceeded-1)
## Constructors
@@ -95,22 +94,3 @@ ___
#### Returns
`void`
-
-___
-
-### hasExceeded
-
-▸ **hasExceeded**(`redisClient`, `queue`, `rateLimit`, `cb`): `void`
-
-#### Parameters
-
-| Name | Type |
-| :------ | :------ |
-| `redisClient` | `RedisClient` |
-| `queue` | [`IQueueParams`](../interfaces/IQueueParams.md) |
-| `rateLimit` | [`IQueueRateLimit`](../interfaces/IQueueRateLimit.md) |
-| `cb` | `ICallback`\<`boolean`\> |
-
-#### Returns
-
-`void`
diff --git a/docs/api/classes/QueueScheduledMessages.md b/docs/api/classes/QueueScheduledMessages.md
index a13e43cd..7c8cb5be 100644
--- a/docs/api/classes/QueueScheduledMessages.md
+++ b/docs/api/classes/QueueScheduledMessages.md
@@ -44,7 +44,7 @@ QueueMessagesPaginatorSortedSet.constructor
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`number`\> |
#### Returns
@@ -59,14 +59,14 @@ ___
### getMessages
-▸ **getMessages**(`queue`, `cursor`, `pageSize`, `cb`): `void`
+▸ **getMessages**(`queue`, `page`, `pageSize`, `cb`): `void`
#### Parameters
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
-| `cursor` | `number` |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
+| `page` | `number` |
| `pageSize` | `number` |
| `cb` | `ICallback`\<[`IQueueMessagesPage`](../interfaces/IQueueMessagesPage.md)\<[`IConsumableMessage`](../interfaces/IConsumableMessage.md)\>\> |
@@ -88,7 +88,7 @@ ___
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](../interfaces/IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`void`\> |
#### Returns
diff --git a/docs/api/enums/EQueueDeliveryModel.md b/docs/api/enums/EQueueDeliveryModel.md
new file mode 100644
index 00000000..b6b57c8b
--- /dev/null
+++ b/docs/api/enums/EQueueDeliveryModel.md
@@ -0,0 +1,22 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / EQueueDeliveryModel
+
+# Enumeration: EQueueDeliveryModel
+
+## Table of contents
+
+### Enumeration Members
+
+- [POINT\_TO\_POINT](EQueueDeliveryModel.md#point_to_point)
+- [PUB\_SUB](EQueueDeliveryModel.md#pub_sub)
+
+## Enumeration Members
+
+### POINT\_TO\_POINT
+
+• **POINT\_TO\_POINT** = ``0``
+
+___
+
+### PUB\_SUB
+
+• **PUB\_SUB** = ``1``
diff --git a/docs/api/enums/EQueueProperty.md b/docs/api/enums/EQueueProperty.md
index 34f5e3e4..05ac3e7a 100644
--- a/docs/api/enums/EQueueProperty.md
+++ b/docs/api/enums/EQueueProperty.md
@@ -6,6 +6,7 @@
### Enumeration Members
+- [DELIVERY\_MODEL](EQueueProperty.md#delivery_model)
- [EXCHANGE](EQueueProperty.md#exchange)
- [MESSAGES\_COUNT](EQueueProperty.md#messages_count)
- [QUEUE\_TYPE](EQueueProperty.md#queue_type)
@@ -13,6 +14,12 @@
## Enumeration Members
+### DELIVERY\_MODEL
+
+• **DELIVERY\_MODEL** = ``4``
+
+___
+
### EXCHANGE
• **EXCHANGE** = ``2``
diff --git a/docs/api/interfaces/IConsumableMessage.md b/docs/api/interfaces/IConsumableMessage.md
index 82f2fbc5..7dc48d0b 100644
--- a/docs/api/interfaces/IConsumableMessage.md
+++ b/docs/api/interfaces/IConsumableMessage.md
@@ -2,12 +2,21 @@
# Interface: IConsumableMessage
+## Hierarchy
+
+- `Omit`\<[`ProducibleMessage`](../classes/ProducibleMessage.md), ``"setBody"`` \| ``"setConsumeTimeout"`` \| ``"setPriority"`` \| ``"setTTL"`` \| ``"setFanOut"`` \| ``"setQueue"`` \| ``"setTopic"`` \| ``"setRetryDelay"`` \| ``"setRetryThreshold"`` \| ``"setScheduledRepeatPeriod"`` \| ``"setScheduledRepeat"`` \| ``"setScheduledCRON"`` \| ``"setScheduledDelay"`` \| ``"disablePriority"`` \| ``"resetScheduledParams"`` \| ``"setExchange"`` \| ``"getExchange"``\>
+
+- `Pick`\<`MessageEnvelope`, ``"getScheduledMessageId"`` \| ``"getDestinationQueue"`` \| ``"getStatus"`` \| ``"getPublishedAt"`` \| ``"getScheduledAt"`` \| ``"getId"`` \| ``"toJSON"`` \| ``"getExchange"`` \| ``"getConsumerGroupId"``\>
+
+ ↳ **`IConsumableMessage`**
+
## Table of contents
### Methods
- [getBody](IConsumableMessage.md#getbody)
- [getConsumeTimeout](IConsumableMessage.md#getconsumetimeout)
+- [getConsumerGroupId](IConsumableMessage.md#getconsumergroupid)
- [getCreatedAt](IConsumableMessage.md#getcreatedat)
- [getDestinationQueue](IConsumableMessage.md#getdestinationqueue)
- [getExchange](IConsumableMessage.md#getexchange)
@@ -60,6 +69,20 @@ Omit.getConsumeTimeout
___
+### getConsumerGroupId
+
+▸ **getConsumerGroupId**(): ``null`` \| `string`
+
+#### Returns
+
+``null`` \| `string`
+
+#### Inherited from
+
+Pick.getConsumerGroupId
+
+___
+
### getCreatedAt
▸ **getCreatedAt**(): `number`
diff --git a/docs/api/interfaces/IConsumerMessageHandlerArgs.md b/docs/api/interfaces/IConsumerMessageHandlerArgs.md
index 9dcc4ab6..d3a12d6e 100644
--- a/docs/api/interfaces/IConsumerMessageHandlerArgs.md
+++ b/docs/api/interfaces/IConsumerMessageHandlerArgs.md
@@ -19,4 +19,4 @@ ___
### queue
-• **queue**: [`IQueueParams`](IQueueParams.md)
+• **queue**: [`IQueueParsedParams`](IQueueParsedParams.md)
diff --git a/docs/api/interfaces/IEventListener.md b/docs/api/interfaces/IEventListener.md
index 12d5d549..76c29981 100644
--- a/docs/api/interfaces/IEventListener.md
+++ b/docs/api/interfaces/IEventListener.md
@@ -45,4 +45,4 @@ ___
#### Returns
-`void`
\ No newline at end of file
+`void`
diff --git a/docs/api/interfaces/IMessageSerialized.md b/docs/api/interfaces/IMessageSerialized.md
index 1d0cf9b5..3e675755 100644
--- a/docs/api/interfaces/IMessageSerialized.md
+++ b/docs/api/interfaces/IMessageSerialized.md
@@ -8,6 +8,7 @@
- [body](IMessageSerialized.md#body)
- [consumeTimeout](IMessageSerialized.md#consumetimeout)
+- [consumerGroupId](IMessageSerialized.md#consumergroupid)
- [createdAt](IMessageSerialized.md#createdat)
- [destinationQueue](IMessageSerialized.md#destinationqueue)
- [exchange](IMessageSerialized.md#exchange)
@@ -34,6 +35,12 @@ ___
___
+### consumerGroupId
+
+• **consumerGroupId**: ``null`` \| `string`
+
+___
+
### createdAt
• **createdAt**: `number`
diff --git a/docs/api/interfaces/IQueueConsumerGroupParams.md b/docs/api/interfaces/IQueueConsumerGroupParams.md
new file mode 100644
index 00000000..f34fcf82
--- /dev/null
+++ b/docs/api/interfaces/IQueueConsumerGroupParams.md
@@ -0,0 +1,22 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / IQueueConsumerGroupParams
+
+# Interface: IQueueConsumerGroupParams
+
+## Table of contents
+
+### Properties
+
+- [groupId](IQueueConsumerGroupParams.md#groupid)
+- [queue](IQueueConsumerGroupParams.md#queue)
+
+## Properties
+
+### groupId
+
+• **groupId**: ``null`` \| `string`
+
+___
+
+### queue
+
+• **queue**: `string` \| [`IQueueParams`](IQueueParams.md)
diff --git a/docs/api/interfaces/IQueueGroupConsumersPendingCount.md b/docs/api/interfaces/IQueueGroupConsumersPendingCount.md
new file mode 100644
index 00000000..6c08a83e
--- /dev/null
+++ b/docs/api/interfaces/IQueueGroupConsumersPendingCount.md
@@ -0,0 +1,7 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / IQueueGroupConsumersPendingCount
+
+# Interface: IQueueGroupConsumersPendingCount
+
+## Indexable
+
+▪ [key: `string`]: `number`
diff --git a/docs/api/interfaces/IQueueMessages.md b/docs/api/interfaces/IQueueMessages.md
index 7946e02e..681d3bbd 100644
--- a/docs/api/interfaces/IQueueMessages.md
+++ b/docs/api/interfaces/IQueueMessages.md
@@ -24,7 +24,7 @@
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`number`\> |
#### Returns
@@ -41,7 +41,7 @@ ___
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `page` | `number` |
| `pageSize` | `number` |
| `cb` | `ICallback`\<[`IQueueMessagesPage`](IQueueMessagesPage.md)\<[`IConsumableMessage`](IConsumableMessage.md)\>\> |
@@ -60,7 +60,7 @@ ___
| Name | Type |
| :------ | :------ |
-| `queue` | `string` \| [`IQueueParams`](IQueueParams.md) |
+| `queue` | [`TQueueExtendedParams`](../README.md#tqueueextendedparams) |
| `cb` | `ICallback`\<`void`\> |
#### Returns
diff --git a/docs/api/interfaces/IQueueMessagesCount.md b/docs/api/interfaces/IQueueMessagesCount.md
index 298c7bc3..ac4ceb72 100644
--- a/docs/api/interfaces/IQueueMessagesCount.md
+++ b/docs/api/interfaces/IQueueMessagesCount.md
@@ -27,7 +27,7 @@ ___
### pending
-• **pending**: `number`
+• **pending**: `number` \| [`IQueueGroupConsumersPendingCount`](IQueueGroupConsumersPendingCount.md)
___
diff --git a/docs/api/interfaces/IQueueMessagesRequeuable.md b/docs/api/interfaces/IQueueMessagesRequeuable.md
new file mode 100644
index 00000000..f3fdd60a
--- /dev/null
+++ b/docs/api/interfaces/IQueueMessagesRequeuable.md
@@ -0,0 +1,32 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / IQueueMessagesRequeuable
+
+# Interface: IQueueMessagesRequeuable
+
+## Implemented by
+
+- [`QueueAcknowledgedMessages`](../classes/QueueAcknowledgedMessages.md)
+- [`QueueDeadLetteredMessages`](../classes/QueueDeadLetteredMessages.md)
+
+## Table of contents
+
+### Methods
+
+- [requeueMessage](IQueueMessagesRequeuable.md#requeuemessage)
+
+## Methods
+
+### requeueMessage
+
+▸ **requeueMessage**(`queue`, `messageId`, `cb`): `void`
+
+#### Parameters
+
+| Name | Type |
+| :------ | :------ |
+| `queue` | `string` \| [`IQueueParams`](IQueueParams.md) |
+| `messageId` | `string` |
+| `cb` | `ICallback`\<`void`\> |
+
+#### Returns
+
+`void`
diff --git a/docs/api/interfaces/IQueueParsedParams.md b/docs/api/interfaces/IQueueParsedParams.md
new file mode 100644
index 00000000..14e68d79
--- /dev/null
+++ b/docs/api/interfaces/IQueueParsedParams.md
@@ -0,0 +1,22 @@
+[RedisSMQ](../../../README.md) / [Docs](../../README.md) / [API Reference](../README.md) / IQueueParsedParams
+
+# Interface: IQueueParsedParams
+
+## Table of contents
+
+### Properties
+
+- [groupId](IQueueParsedParams.md#groupid)
+- [queueParams](IQueueParsedParams.md#queueparams)
+
+## Properties
+
+### groupId
+
+• **groupId**: ``null`` \| `string`
+
+___
+
+### queueParams
+
+• **queueParams**: [`IQueueParams`](IQueueParams.md)
diff --git a/docs/api/interfaces/IQueueProperties.md b/docs/api/interfaces/IQueueProperties.md
index d6f21d50..634c08b4 100644
--- a/docs/api/interfaces/IQueueProperties.md
+++ b/docs/api/interfaces/IQueueProperties.md
@@ -6,6 +6,7 @@
### Properties
+- [deliveryModel](IQueueProperties.md#deliverymodel)
- [exchange](IQueueProperties.md#exchange)
- [messagesCount](IQueueProperties.md#messagescount)
- [queueType](IQueueProperties.md#queuetype)
@@ -13,6 +14,12 @@
## Properties
+### deliveryModel
+
+• **deliveryModel**: [`EQueueDeliveryModel`](../enums/EQueueDeliveryModel.md)
+
+___
+
### exchange
• **exchange**: ``null`` \| `string`
diff --git a/docs/exchanges-and-delivery-models.md b/docs/exchanges-and-delivery-models.md
new file mode 100644
index 00000000..c83ab451
--- /dev/null
+++ b/docs/exchanges-and-delivery-models.md
@@ -0,0 +1,13 @@
+[RedisSMQ](../README.md) / [Docs](README.md) / Exchanges and Delivery Models
+
+# Exchanges and Delivery Models
+
+![RedisSMQ Exchanges and Delivery Models](redis-smq-exchanges-and-delivery-models.png)
+
+[Message Exchanges](docs/message-exchanges.md) should not be confused with [Queue Delivery Models](docs/queue-delivery-models.md).
+
+Message exchanges allow publishing a message a one or many queues based on the given exchange.
+
+On the other hand, queue delivery models allow delivering a message to one consumer or to all consumers.
+
+Message exchanges and queue delivery models can be combined in order to create, as shown in the diagram above, complex publishing-delivering models based on various criteria that may be defined depending on your application needs.
diff --git a/docs/queue-delivery-models.md b/docs/queue-delivery-models.md
new file mode 100644
index 00000000..047d0ae5
--- /dev/null
+++ b/docs/queue-delivery-models.md
@@ -0,0 +1,152 @@
+[RedisSMQ](../README.md) / [Docs](README.md) / Queue Delivery Models
+
+# Queue Delivery Models
+
+When it comes to message delivery RedisSMQ provides 2 reliable models: Point-2-Point and Pub/Sub.
+
+## Point-2-Point Delivery Model
+
+![RedisSMQ Point-2-Point Delivery Model](redis-smq-point-2-point-delivery-model.png)
+
+In the Point-2-Point model, a message is produced to a Point-2-Point queue and then delivered and consumed at a time only by one consumer.
+
+### Creating a Point-2-Point Queue
+
+```javascript
+const { Queue, EQueueDeliveryModel, EQueueType } = require('redis-smq');
+
+const queue = new Queue();
+queue.save('my-queue', EQueueType.LIFO_QUEUE, EQueueDeliveryModel.POINT_TO_POINT, (err, reply) => {
+ if (err) console.log(err);
+ else console.log('Successfully created', reply)
+})
+```
+
+See [Queue.prototype.save()](docs/api/classes/Queue.md#save) for more details.
+
+### Publishing a Message to a Point-2-Point Queue
+
+```javascript
+const { Producer, ProducibleMessage } = require('redis-smq');
+
+const message = new ProducibleMessage();
+message.setBody('hello world').setQueue('my-queue');
+
+const producer = new Producer();
+producer.run((err) => {
+ if (err) console.log(err);
+ else producer.produce(message, (err, reply) => {
+ if (err) console.log(err);
+ else console.log('Successfully produced', reply);
+ })
+})
+```
+
+See [Producer.prototype.produce()](docs/api/classes/Producer.md#produce) for more details.
+
+### Consuming a message from a Point-2-Point Queue
+
+```javascript
+const { Consumer } = require('redis-smq');
+
+const consumer = new Consumer();
+
+const messageHandler = (msg, cb) => cb(); // acknowledging
+consumer.consume('my-queue', messageHandler, (err) => {
+ if (err) console.log(err);
+ else console.log('MessageHandler added');
+});
+consumer.run((err) => {
+ if (err) console.log(err);
+})
+```
+
+## Pub/Sub Delivery Model
+
+### Overview
+
+![RedisSMQ Pub/Sub Delivery Model High-level View](redis-smq-pubsub-delivery-model-highlevel-view.png)
+
+In the Pub/Sub model, on the other hand, a message is delivered and consumed by all consumers of a Pub/Sub queue.
+
+From a high-level view the Pub/Sub model maybe illustrated as shown in the diagram above.
+
+Each consumer receives and processes a copy of the produced message.
+
+### Consumer Groups
+
+![RedisSMQ Pub/Sub Delivery Model](redis-smq-pubsub-delivery-model.png)
+
+To consume messages from a Pub/Sub queue, a consumer group is required.
+
+In fact, when publishing a message to a pub/sub queue, the message is published to all consumer groups of the given queue.
+
+Within a consumer group, only one consumer receives the message.
+
+For a consumer group, unacknowledged messages are retried in the same manner as for a Point-2-Point queue.
+
+When `retryTreshold` is exceeded failed messages from all consumer groups are stored in the dead-letter-queue of a given Pub/Sub queue.
+
+### Creating a Pub/Sub Queue
+
+```javascript
+const { Queue, EQueueDeliveryModel, EQueueType } = require('redis-smq');
+
+const queue = new Queue();
+queue.save('my-pubsub-queue', EQueueType.LIFO_QUEUE, EQueueDeliveryModel.PUB_SUB, (err, reply) => {
+ if (err) console.log(err);
+ else console.log('Successfully created', reply)
+})
+```
+
+See [Queue.prototype.save()](docs/api/classes/Queue.md#save) for more details.
+
+### Creating Consumer Groups
+
+If it does not exist, a consumer group of a given queue is created automatically when consuming messages from the queue.
+
+Consumer groups may be also created manually using the [ConsumerGroups.saveConsumerGroup()](docs/api/classes/ConsumerGroups.md) method.
+
+See [ConsumerGroups](docs/api/classes/ConsumerGroups.md) for managing consumer groups.
+
+### Publishing a Message to a Pub/Sub Queue
+
+```javascript
+const { ProducibleMessage, Producer } = require('redis-smq');
+
+const message = new ProducibleMessage();
+message.setBody('hello world').setQueue('my-pubsub-queue');
+
+const producer = new Producer();
+producer.run((err) => {
+ if (err) console.log(err);
+ else producer.produce(message, (err, reply) => {
+ if (err) console.log(err);
+ else console.log('Successfully produced', reply);
+ })
+})
+```
+
+When producing a message to a Pub/Sub queue, if the queue has no consumer groups an error will be returned. So make sure
+the queue has at least one consumer group before publishing messages.
+
+See [Producer.prototype.produce()](docs/api/classes/Producer.md#produce) for more details.
+
+### Consuming a message from a Pub/Sub Queue
+
+```javascript
+const { Consumer } = require('redis-smq');
+
+const consumer = new Consumer();
+
+const messageHandler = (msg, cb) => cb(); // acknowledging
+consumer.consume({ queue: 'my-pubsub-queue', groupId: 'my-app-group-1' }, messageHandler, (err) => {
+ if (err) console.log(err);
+ else console.log('MessageHandler added');
+});
+consumer.run((err) => {
+ if (err) console.log(err);
+})
+```
+
+Please do not forget to provide the consumer group ID when consuming messages from a Pub/Sub queue.
diff --git a/docs/redis-smq-exchanges-and-delivery-models.png b/docs/redis-smq-exchanges-and-delivery-models.png
new file mode 100644
index 00000000..ad883d04
Binary files /dev/null and b/docs/redis-smq-exchanges-and-delivery-models.png differ
diff --git a/docs/redis-smq-point-2-point-delivery-model.png b/docs/redis-smq-point-2-point-delivery-model.png
new file mode 100644
index 00000000..20d53fb6
Binary files /dev/null and b/docs/redis-smq-point-2-point-delivery-model.png differ
diff --git a/docs/redis-smq-pubsub-delivery-model-highlevel-view.png b/docs/redis-smq-pubsub-delivery-model-highlevel-view.png
new file mode 100644
index 00000000..59016ee4
Binary files /dev/null and b/docs/redis-smq-pubsub-delivery-model-highlevel-view.png differ
diff --git a/docs/redis-smq-pubsub-delivery-model.png b/docs/redis-smq-pubsub-delivery-model.png
new file mode 100644
index 00000000..da5e229e
Binary files /dev/null and b/docs/redis-smq-pubsub-delivery-model.png differ
diff --git a/examples/javascript/using-async-await.cjs b/examples/javascript/using-async-await.cjs
index 22027db2..4f6ef3b6 100644
--- a/examples/javascript/using-async-await.cjs
+++ b/examples/javascript/using-async-await.cjs
@@ -15,9 +15,10 @@ const {
ProducibleMessage,
Queue,
EQueueType,
+ EQueueDeliveryMode,
Configuration,
disconnect,
-} = require('../..'); // redis-smq
+} = require('../..');
const config = {
namespace: 'ns1',
@@ -56,7 +57,11 @@ const createQueue = async () => {
const exists = await queue.existsAsync('test_queue');
if (!exists) {
// Creating a queue (a LIFO queue)
- await queue.saveAsync('test_queue', EQueueType.LIFO_QUEUE);
+ await queue.saveAsync(
+ 'test_queue',
+ EQueueType.LIFO_QUEUE,
+ EQueueDeliveryMode.POINT_TO_POINT,
+ );
await promisify(disconnect)();
}
};
diff --git a/examples/javascript/using-async-await.js b/examples/javascript/using-async-await.js
index de0cc4ce..c8421f2c 100644
--- a/examples/javascript/using-async-await.js
+++ b/examples/javascript/using-async-await.js
@@ -15,6 +15,7 @@ import {
ProducibleMessage,
Queue,
EQueueType,
+ EQueueDeliveryMode,
Configuration,
disconnect,
} from '../..'; // redis-smq
@@ -58,7 +59,11 @@ const createQueue = async () => {
const exists = await queue.existsAsync('test_queue');
if (!exists) {
// Creating a queue (a LIFO queue)
- await queue.saveAsync('test_queue', EQueueType.LIFO_QUEUE);
+ await queue.saveAsync(
+ 'test_queue',
+ EQueueType.LIFO_QUEUE,
+ EQueueDeliveryMode.POINT_TO_POINT,
+ );
await promisify(disconnect)();
}
};
diff --git a/examples/javascript/using-callbacks.cjs b/examples/javascript/using-callbacks.cjs
index e37220a3..f16ae576 100644
--- a/examples/javascript/using-callbacks.cjs
+++ b/examples/javascript/using-callbacks.cjs
@@ -16,6 +16,7 @@ const {
Configuration,
disconnect,
EQueueType,
+ EQueueDeliveryMode,
} = require('../..'); // redis-smq
const config = {
@@ -54,10 +55,15 @@ const createQueue = (cb) => {
if (err) cb(err);
else if (!reply) {
// Creating a queue (a LIFO queue)
- queue.save('test_queue', EQueueType.LIFO_QUEUE, (err) => {
- if (err) cb(err);
- else disconnect(cb);
- });
+ queue.save(
+ 'test_queue',
+ EQueueType.LIFO_QUEUE,
+ EQueueDeliveryMode.POINT_TO_POINT,
+ (err) => {
+ if (err) cb(err);
+ else disconnect(cb);
+ },
+ );
} else cb();
});
};
diff --git a/examples/javascript/using-callbacks.js b/examples/javascript/using-callbacks.js
index d6153c74..a377936e 100644
--- a/examples/javascript/using-callbacks.js
+++ b/examples/javascript/using-callbacks.js
@@ -16,6 +16,7 @@ import {
Configuration,
disconnect,
EQueueType,
+ EQueueDeliveryMode,
} from '../..'; // redis-smq
const config = {
@@ -54,10 +55,15 @@ const createQueue = (cb) => {
if (err) cb(err);
else if (!reply) {
// Creating a queue (a LIFO queue)
- queue.save('test_queue', EQueueType.LIFO_QUEUE, (err) => {
- if (err) cb(err);
- else disconnect(cb);
- });
+ queue.save(
+ 'test_queue',
+ EQueueType.LIFO_QUEUE,
+ EQueueDeliveryMode.POINT_TO_POINT,
+ (err) => {
+ if (err) cb(err);
+ else disconnect(cb);
+ },
+ );
} else cb();
});
};
diff --git a/examples/typescript/using-async-await.ts b/examples/typescript/using-async-await.ts
index 0b8c277e..711c13c6 100644
--- a/examples/typescript/using-async-await.ts
+++ b/examples/typescript/using-async-await.ts
@@ -20,6 +20,7 @@ import {
disconnect,
} from '../..'; // redis-smq
import { Configuration } from '../../src/config/configuration';
+import { EQueueDeliveryModel } from '../../types';
export const config: IRedisSMQConfig = {
namespace: 'ns1',
@@ -58,7 +59,11 @@ const createQueue = async () => {
const exists = await queue.existsAsync('test_queue');
if (!exists) {
// Creating a queue (a LIFO queue)
- await queue.saveAsync('test_queue', EQueueType.LIFO_QUEUE);
+ await queue.saveAsync(
+ 'test_queue',
+ EQueueType.LIFO_QUEUE,
+ EQueueDeliveryModel.POINT_TO_POINT,
+ );
await promisify(disconnect)();
}
};
diff --git a/examples/typescript/using-callbacks.ts b/examples/typescript/using-callbacks.ts
index 05ed30a3..ebe00ea7 100644
--- a/examples/typescript/using-callbacks.ts
+++ b/examples/typescript/using-callbacks.ts
@@ -19,6 +19,7 @@ import {
disconnect,
} from '../..'; // redis-smq
import { Configuration } from '../../src/config/configuration';
+import { EQueueDeliveryModel } from '../../types';
export const config: IRedisSMQConfig = {
namespace: 'ns1',
@@ -56,10 +57,15 @@ const createQueue = (cb: ICallback
): void => {
if (err) cb(err);
else if (!reply) {
// Creating a queue (a LIFO queue)
- queue.save('test_queue', EQueueType.LIFO_QUEUE, (err) => {
- if (err) cb(err);
- else disconnect(cb);
- });
+ queue.save(
+ 'test_queue',
+ EQueueType.LIFO_QUEUE,
+ EQueueDeliveryModel.POINT_TO_POINT,
+ (err) => {
+ if (err) cb(err);
+ else disconnect(cb);
+ },
+ );
} else cb();
});
};