Skip to content

Commit a44cb38

Browse files
handle sigterm signal
1 parent 1af602b commit a44cb38

3 files changed

Lines changed: 53 additions & 4 deletions

File tree

test/rabbit.test.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import Exchange from '../ts/exchange';
77
import * as ReplyQueue from '../ts/reply-queue';
88
import * as DelayQueue from '../ts/delay-queue';
99
import * as amqp from 'amqplib';
10+
import { randomUUID } from 'crypto';
1011

1112
const sandbox = sinon.createSandbox();
1213

1314
describe('Test rabbit class', function() {
14-
let rabbit: Rabbit;
15+
let rabbit: Rabbit | null;
1516

1617
before(function() {
1718
this.url = process.env.RABBIT_URL || 'amqp://localhost';
@@ -364,4 +365,32 @@ describe('Test rabbit class', function() {
364365
await rabbit.destroyQueue(this.name);
365366
stub.calledWith(rabbit.consumeChannel, `test_${this.name}`).should.be.true();
366367
});
368+
369+
it('should register sigtermHandler in SIGTERM process listeners and remove on close', async function() {
370+
rabbit = new Rabbit(this.url);
371+
await rabbit.connected;
372+
373+
const handler = (rabbit as any).sigtermHandler;
374+
375+
process.listeners('SIGTERM').should.containEql(handler);
376+
377+
rabbit.close();
378+
rabbit = null;
379+
380+
process.listeners('SIGTERM').should.not.containEql(handler);
381+
});
382+
383+
it('should call unsubscribe for all queues on SIGTERM', async function() {
384+
const stub = sandbox.stub(Queue.prototype, 'unsubscribe').resolves();
385+
386+
rabbit = new Rabbit(this.url);
387+
await rabbit.connected;
388+
389+
const handler = () => ({});
390+
await rabbit.createQueue(randomUUID().toString(), { exclusive: true }, handler);
391+
await rabbit.createQueue(randomUUID().toString(), { exclusive: true }, handler);
392+
393+
(rabbit as any).sigtermHandler();
394+
stub.calledTwice.should.be.true();
395+
});
367396
});

ts/queue.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,13 @@ export default class Queue {
6969
async subscribe(handler: (msg: any, ack: (error?, reply?) => any) => any) {
7070
await this.created;
7171
this.handler = handler;
72-
let tag = await this.channel.consume(this.name, this.onMessage.bind(this), { noAck: this.options.noAck });
73-
this.tag = tag;
72+
this.tag = await this.channel.consume(this.name, this.onMessage.bind(this), { noAck: this.options.noAck });
7473
}
7574

7675
async unsubscribe() {
77-
await this.channel.cancel(this.tag.consumerTag);
76+
if (this.tag) {
77+
await this.channel.cancel(this.tag.consumerTag);
78+
}
7879
this.handler = null;
7980
this.tag = null;
8081
}

ts/rabbit.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default class Rabbit extends EventEmitter {
2727
public socketOptions;
2828
private defaultQueueType: string | undefined;
2929
public logger: ReturnType<typeof getLogger>;
30+
private readonly sigtermHandler: () => void;
3031

3132
constructor(
3233
public url: string,
@@ -58,7 +59,10 @@ export default class Rabbit extends EventEmitter {
5859
this.scheduledPublish = scheduledPublish;
5960
this.socketOptions = socketOptions;
6061
this.defaultQueueType = defaultQueueType;
62+
this.sigtermHandler = this.handleSigterm.bind(this);
6163
this.reconnect();
64+
65+
process.once('SIGTERM', this.sigtermHandler);
6266
}
6367

6468
private async connect() {
@@ -239,7 +243,22 @@ export default class Rabbit extends EventEmitter {
239243
}
240244

241245
async close() {
246+
process.off('SIGTERM', this.sigtermHandler);
247+
242248
await this.consumeConnection.close();
243249
await this.publishConnection.close();
244250
}
251+
252+
private handleSigterm() {
253+
this.logger.info('Received SIGTERM. Cancelling consumers..');
254+
255+
for (const queue of Object.values(this.queues)) {
256+
queue.unsubscribe()
257+
.then(() => {
258+
this.logger.debug(`Consumer for queue ${queue.name} cancelled.`);
259+
}).catch(e => {
260+
this.logger.error(`Consumer for queue ${queue.name} failed to cancel`, e);
261+
});
262+
}
263+
}
245264
}

0 commit comments

Comments
 (0)