@pixellot/pxlt-rabbit-handler
Version:
A generic class that handles RabbitMQ connection, consume and produce functionality.
239 lines (171 loc) • 7.98 kB
JavaScript
const config = require('config');
const RabbitHandler = require('../../../lib/rabbitHandler');
const { delay } = require('../utilities/functions');
const { setupSubscriptionRetry, setupSimpleExcahngeAndQueue } = require('../utilities/rmq-setup-scripts');
const VHOST = config.get('rmq.vhost');
const url = new URL('amqp://localhost');
url.host = config.get('rmq.host');
url.port = config.get('rmq.amqpPort');
url.username = config.get('rmq.username');
url.password = config.get('rmq.password');
url.pathname = VHOST;
const RMQ_CONNECTION_STRING = url.toString();
describe('rabbitHandler', () => {
const cleanRMQResources = async () => {
await global.__RMQ_HTTP_API__.deleteAllUserExchangesInVhost(VHOST);
await global.__RMQ_HTTP_API__.deleteAllQueuesInVhost(VHOST);
};
beforeEach(async () => {
await cleanRMQResources();
});
it('message retry logic, prefetch 1', async () => {
expect.hasAssertions();
await setupSubscriptionRetry(global.__RMQ_CHANNEL__);
const comsumerRabbitHandler = new RabbitHandler(RMQ_CONNECTION_STRING);
await comsumerRabbitHandler.connect();
const mockCallback = jest.fn((pxltRabbitHandlerMessageWrapper) => {
comsumerRabbitHandler.retry(pxltRabbitHandlerMessageWrapper);
});
await comsumerRabbitHandler.consume('subscriptions', mockCallback, {
prefetch: 1,
retryConfig: {
exchange: 'subscriptions-exchange.retry',
retryDelaysInSeconds: [1, 2, 3, 4]
}
});
await new Promise((resolve, reject) => {
global.__RMQ_CHANNEL__.publish('subscriptions-exchange', 'message', Buffer.from(JSON.stringify({ foo: 'bar' })), {}, (error) => {
if (error) {
return reject(error);
}
return resolve();
});
});
await delay(1000 * 15);
expect(mockCallback).toHaveBeenCalledTimes(5);
await comsumerRabbitHandler.gracefullyDisconnect();
}, 1000 * 30);
it('message retry logic, prefetch 100', async () => {
expect.hasAssertions();
await setupSubscriptionRetry(global.__RMQ_CHANNEL__);
const comsumerRabbitHandler = new RabbitHandler(RMQ_CONNECTION_STRING);
await comsumerRabbitHandler.connect();
const mockCallback = jest.fn((pxltRabbitHandlerMessageWrapper) => {
comsumerRabbitHandler.retry(pxltRabbitHandlerMessageWrapper);
});
await comsumerRabbitHandler.consume('subscriptions', mockCallback, {
prefetch: 100,
retryConfig: {
exchange: 'subscriptions-exchange.retry',
retryDelaysInSeconds: [1, 2, 3, 4]
}
});
const publishPromises = [];
for (let i = 0; i < 100; i++) {
publishPromises.push(new Promise((resolve, reject) => {
global.__RMQ_CHANNEL__.publish('subscriptions-exchange', 'message', Buffer.from(JSON.stringify({ foo: 'bar' })), {}, (error) => {
if (error) {
return reject(error);
}
return resolve();
});
}));
}
await Promise.all(publishPromises);
await delay(1000 * 15);
expect(mockCallback).toHaveBeenCalledTimes(500);
await comsumerRabbitHandler.gracefullyDisconnect();
}, 1000 * 30);
it('gracefull termination with stopConsume', async () => {
expect.hasAssertions();
await setupSimpleExcahngeAndQueue(global.__RMQ_CHANNEL__);
const comsumerRabbitHandler = new RabbitHandler(RMQ_CONNECTION_STRING);
await comsumerRabbitHandler.connect();
const catchMock = jest.fn();
const mockCallback = jest.fn(async (pxltRabbitHandlerMessageWrapper) => {
const payload = JSON.parse(pxltRabbitHandlerMessageWrapper.message.content.toString());
await delay(payload.delay);
comsumerRabbitHandler.ack(pxltRabbitHandlerMessageWrapper, false)
.catch(catchMock);
});
await comsumerRabbitHandler.consume('subscriptions', mockCallback, {
prefetch: 100
});
const fastMessagesPublishPromises = [];
for (let i = 0; i < 10; i++) {
fastMessagesPublishPromises.push(new Promise((resolve, reject) => {
global.__RMQ_CHANNEL__.publish('subscriptions-exchange', 'message', Buffer.from(JSON.stringify({ delay: 1000 })), {}, (error) => {
if (error) {
return reject(error);
}
return resolve();
});
}));
}
await Promise.all(fastMessagesPublishPromises);
const slowMessagesPublishPromises = [];
for (let i = 0; i < 10; i++) {
slowMessagesPublishPromises.push(new Promise((resolve, reject) => {
global.__RMQ_CHANNEL__.publish('subscriptions-exchange', 'message', Buffer.from(JSON.stringify({ delay: 5000 })), {}, (error) => {
if (error) {
return reject(error);
}
return resolve();
});
}));
}
await Promise.all(slowMessagesPublishPromises);
await delay(1000 * 2);
await comsumerRabbitHandler.stopConsumer('subscriptions');
await delay(1000 * 8);
expect(mockCallback).toHaveBeenCalledTimes(20);
expect(catchMock).toHaveBeenCalledTimes(0);
await comsumerRabbitHandler.gracefullyDisconnect();
}, 1000 * 30);
it('gracefull termination with cancelConsumer', async () => {
expect.hasAssertions();
await setupSimpleExcahngeAndQueue(global.__RMQ_CHANNEL__);
const comsumerRabbitHandler = new RabbitHandler(RMQ_CONNECTION_STRING);
await comsumerRabbitHandler.connect();
const catchMock = jest.fn();
const mockCallback = jest.fn(async (pxltRabbitHandlerMessageWrapper) => {
const payload = JSON.parse(pxltRabbitHandlerMessageWrapper.message.content.toString());
await delay(payload.delay);
comsumerRabbitHandler.ack(pxltRabbitHandlerMessageWrapper, false)
.catch(catchMock);
});
await comsumerRabbitHandler.consume('subscriptions', mockCallback, {
prefetch: 100
});
const fastMessagesPublishPromises = [];
for (let i = 0; i < 10; i++) {
fastMessagesPublishPromises.push(new Promise((resolve, reject) => {
global.__RMQ_CHANNEL__.publish('subscriptions-exchange', 'message', Buffer.from(JSON.stringify({ delay: 1000 })), {}, (error) => {
if (error) {
return reject(error);
}
return resolve();
});
}));
}
await Promise.all(fastMessagesPublishPromises);
const slowMessagesPublishPromises = [];
for (let i = 0; i < 10; i++) {
slowMessagesPublishPromises.push(new Promise((resolve, reject) => {
global.__RMQ_CHANNEL__.publish('subscriptions-exchange', 'message', Buffer.from(JSON.stringify({ delay: 5000 })), {}, (error) => {
if (error) {
return reject(error);
}
return resolve();
});
}));
}
await Promise.all(slowMessagesPublishPromises);
await delay(1000 * 2);
await comsumerRabbitHandler.cancelConsumer('subscriptions');
await delay(1000 * 8);
expect(mockCallback).toHaveBeenCalledTimes(20);
expect(catchMock).toHaveBeenCalledTimes(10);
await comsumerRabbitHandler.gracefullyDisconnect();
}, 1000 * 30);
});