Skip to content

Commit 23dc38e

Browse files
authored
Merge pull request #70 from Workable/classic-queue-args
Enforce classic queue type for non-durable and exclusive queues
2 parents d724ab5 + bd219f1 commit 23dc38e

4 files changed

Lines changed: 62 additions & 1 deletion

File tree

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,18 @@ new DemoHandler('demoQueue', rabbit, {
250250
rabbit.publish('demoQueue', { test: 'data' }, { correlationId: '4' });
251251
```
252252

253+
### Queue Type Behavior
254+
255+
You can control the type of queues created with the `defaultQueueType` option in your Rabbit configuration.
256+
```javascript
257+
const rabbit = new Rabbit(process.env.RABBIT_URL, { defaultQueueType: 'quorum' });
258+
```
259+
260+
When declaring queues, the following rules apply:
261+
- **Non-durable, exclusive, or auto-delete queues** always use **classic** queue type, since **quorum** queues and **streams** are always durable and not designed for temporary or connection-bound queues.
262+
263+
The type of a queue is **immutable** once it has been declared. Attempting to change it after creation will result in a **PRECONDITION_FAILED** error.
264+
253265
### Changelog
254266

255267
### New in v5.4.x

test/queue.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ describe('Test Queue class', function () {
4747
deadLetterExchange: undefined,
4848
deadLetterRoutingKey: undefined,
4949
maxLength: undefined,
50-
arguments: {}
50+
arguments: { 'x-queue-type': 'classic' }
5151
})
5252
.should.be.true();
5353
});

test/rabbit.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,51 @@ describe('Test rabbit class', function() {
194194
options!.arguments.should.not.have.property('x-max-priority');
195195
});
196196

197+
it('should set queue type to classic when creating a non durable queue', async function() {
198+
const subscription = sandbox.stub(Queue.prototype, 'subscribe');
199+
rabbit = new Rabbit(this.url, { defaultQueueType: 'quorum' });
200+
await rabbit.connected;
201+
const stub = sandbox.stub(rabbit.consumeChannel, 'assertQueue')
202+
.resolves({ queue: this.name, messageCount: 0, consumerCount: 0 });
203+
const handler = () => {};
204+
await rabbit.createQueue(this.name, { durable: false }, handler);
205+
subscription.calledWith(handler).should.be.true();
206+
stub.calledOnce.should.be.true();
207+
const [name, options] = stub.firstCall.args;
208+
name.should.equal(this.name);
209+
options!.arguments['x-queue-type'].should.equals('classic');
210+
});
211+
212+
it('should set queue type to classic when creating an exclusive queue', async function() {
213+
const subscription = sandbox.stub(Queue.prototype, 'subscribe');
214+
rabbit = new Rabbit(this.url, { defaultQueueType: 'quorum' });
215+
await rabbit.connected;
216+
const stub = sandbox.stub(rabbit.consumeChannel, 'assertQueue')
217+
.resolves({ queue: this.name, messageCount: 0, consumerCount: 0 });
218+
const handler = () => {};
219+
await rabbit.createQueue(this.name, { exclusive: true }, handler);
220+
subscription.calledWith(handler).should.be.true();
221+
stub.calledOnce.should.be.true();
222+
const [name, options] = stub.firstCall.args;
223+
name.should.equal(this.name);
224+
options!.arguments['x-queue-type'].should.equals('classic');
225+
});
226+
227+
it('should set queue type to classic when creating an auto delete queue', async function() {
228+
const subscription = sandbox.stub(Queue.prototype, 'subscribe');
229+
rabbit = new Rabbit(this.url, { defaultQueueType: 'quorum' });
230+
await rabbit.connected;
231+
const stub = sandbox.stub(rabbit.consumeChannel, 'assertQueue')
232+
.resolves({ queue: this.name, messageCount: 0, consumerCount: 0 });
233+
const handler = () => {};
234+
await rabbit.createQueue(this.name, { autoDelete: true }, handler);
235+
subscription.calledWith(handler).should.be.true();
236+
stub.calledOnce.should.be.true();
237+
const [name, options] = stub.firstCall.args;
238+
name.should.equal(this.name);
239+
options!.arguments['x-queue-type'].should.equals('classic');
240+
});
241+
197242
it('should unsubscribe', async function() {
198243
const stub = sandbox.stub(Queue.prototype, 'unsubscribe');
199244
rabbit = new Rabbit(this.url);

ts/queue.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ export default class Queue {
5454
if (priority !== undefined) {
5555
queueOptions.arguments = { ...queueOptions.arguments, 'x-max-priority': priority };
5656
}
57+
if (!durable || exclusive || autoDelete) {
58+
queueOptions.arguments ??= {};
59+
queueOptions.arguments['x-queue-type'] = 'classic';
60+
}
5761
if (queueOptions.arguments?.['x-max-priority'] &&
5862
queueOptions.arguments?.['x-queue-type'] === 'quorum') {
5963
logger.warn(`Invalid x-max-priority argument for quorum queue '${this.name}'`);

0 commit comments

Comments
 (0)