peanar
Version:
A job queue for Node.js based on RabbitMQ
113 lines (112 loc) • 3.85 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = __importDefault(require("debug"));
const debug = (0, debug_1.default)('peanar:broker');
const ts_amqp_1 = require("ts-amqp");
const ChannelPool_1 = __importDefault(require("ts-amqp/dist/classes/ChannelPool"));
const exceptions_1 = require("./exceptions");
/**
* Peanar's broker adapter
*/
class PeanarBroker {
config;
conn;
_connectPromise;
pool;
constructor(config) {
this.config = config;
}
_connect = async () => {
debug('_connect()');
const conn = (this.conn = new ts_amqp_1.Connection(this.config.connection));
this.pool = new ChannelPool_1.default(conn, this.config.poolSize, this.config.prefetch);
await conn.start();
await this.pool.open();
conn.once('close', (err) => {
this._connectPromise = undefined;
if (err && err.reply_code >= 400) {
this.connect();
}
});
};
/**
* Initializes adapter connection and channel
*/
connect = async () => {
if (this._connectPromise)
return this._connectPromise;
return (this._connectPromise = this._connect());
};
async shutdown() {
debug('shutdown()');
if (this.pool) {
await this.pool.close();
this.pool = undefined;
debug('pool closed.');
}
if (this.conn) {
this.conn.off('close', this.connect);
await this.conn.close();
this.conn = undefined;
debug('connection closed.');
}
}
async queues(queues) {
await this.connect();
if (!this.pool)
throw new exceptions_1.PeanarAdapterError('Not connected!');
return await Promise.all(this.pool.mapOver(queues, async (ch, queue) => {
return ch.declareQueue(queue);
}));
}
async exchanges(exchanges) {
await this.connect();
if (!this.pool)
throw new exceptions_1.PeanarAdapterError('Not connected!');
return await Promise.all(this.pool.mapOver(exchanges, async (ch, exchange) => {
return ch.declareExchange(exchange);
}));
}
async bindings(bindings) {
await this.connect();
if (!this.pool)
throw new exceptions_1.PeanarAdapterError('Not connected!');
return await Promise.all(this.pool.mapOver(bindings, async (ch, binding) => {
return ch.bindQueue(binding);
}));
}
consume(queue) {
if (!this.pool)
throw new exceptions_1.PeanarAdapterError('Not connected!');
return this.pool.acquireAndRun(ch => ch.basicConsume(queue));
}
consumeOver(queues) {
if (!this.pool)
throw new exceptions_1.PeanarAdapterError('Not connected!');
return this.pool.mapOver(queues, async (ch, queue) => {
return {
queue,
consumer: await ch.basicConsume(queue)
};
});
}
async publish(message) {
await this.connect();
if (!this.pool)
throw new exceptions_1.PeanarAdapterError('Not connected!');
const { channel, release } = await this.pool.acquire();
debug(`publish to channel ${channel.channelNumber}`);
if (channel.basicPublishJson(message.exchange || '', message.routing_key, message.properties, message.body, message.mandatory, message.immediate)) {
release();
return true;
}
else {
channel.once('drain', release);
return false;
}
}
}
exports.default = PeanarBroker;