vulcain-corejs
Version:
Vulcain micro-service framework
138 lines (136 loc) • 5.21 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments)).next());
});
};
const amqp = require("amqplib");
const system_1 = require("./../configurations/globals/system");
class RabbitAdapter {
constructor(address) {
this.address = address;
this.domainHandlers = new Map();
this.initialized = false;
if (!this.address)
throw new Error("Address is required for RabbitAdapter");
if (!address.startsWith("amqp://"))
this.address = "amqp://" + address;
this.address += "/" + system_1.System.environment;
}
startAsync() {
let self = this;
return new Promise((resolve, reject) => {
if (self.initialized) {
return resolve(self);
}
// TODO connection error
self.initialized = true;
system_1.System.log.info(null, "Open rabbitmq connexion on " + system_1.System.removePasswordFromUrl(this.address)); // TODO remove password
amqp.connect(this.address).then((conn) => {
conn.createChannel().then((ch) => {
self.channel = ch;
resolve(self);
});
})
.catch(err => {
system_1.System.log.error(null, err, "Unable to open rabbit connexion");
resolve(self);
});
});
}
/**
* Send domain event (event raises by an action)
* Domain events are shared by all services of any domains
*
* @param {string} domain
* @param {EventData} event
*
* @memberOf RabbitAdapter
*/
sendEvent(domain, event) {
if (!this.channel)
return;
domain = domain.toLowerCase() + "_events";
this.channel.assertExchange(domain, 'fanout', { durable: false });
this.channel.publish(domain, '', new Buffer(JSON.stringify(event)));
}
/**
* Listening for domain events
*
* @param {string} domain
* @param {Function} handler
*
* @memberOf RabbitAdapter
*/
consumeEvents(domain, handler) {
if (!this.channel)
return;
let self = this;
// Since this method can be called many times for a same domain
// all handlers are aggragated on only one binding
domain = domain.toLowerCase() + "_events";
let handlers = this.domainHandlers.get[domain];
if (handlers) {
handlers.push(handler);
return;
}
// First time for this domain, create the binding
handlers = [handler];
this.domainHandlers.set(domain, handlers);
this.channel.assertExchange(domain, 'fanout', { durable: false });
this.channel.assertQueue('', { exclusive: true }).then(queue => {
self.channel.bindQueue(queue.queue, domain, '');
self.channel.consume(queue.queue, (msg) => __awaiter(this, void 0, void 0, function* () {
let obj = JSON.parse(msg.content.toString());
handlers.forEach(h => h(obj));
}), { noAck: true });
});
}
/**
* Task = asynchronous action
* Shared by service instances
*
* @param {string} domain
* @param {string} serviceId
* @param {ActionData} command
*
* @memberOf RabbitAdapter
*/
publishTask(domain, serviceId, command) {
if (!this.channel)
return;
domain = domain.toLowerCase();
this.channel.assertExchange(domain, 'direct', { durable: false });
this.channel.publish(domain, serviceId, new Buffer(JSON.stringify(command)), { persistent: true });
}
/**
* Listening for asynchronous task
*
* @param {string} domain
* @param {string} serviceId
* @param {Function} handler
*
* @memberOf RabbitAdapter
*/
consumeTask(domain, serviceId, handler) {
if (!this.channel)
return;
let self = this;
domain = domain.toLowerCase();
this.channel.assertExchange(domain, 'direct', { durable: false });
this.channel.assertQueue(domain, { durable: true }).then(queue => {
// Channel name = serviceId
self.channel.bindQueue(queue.queue, domain, serviceId);
self.channel.prefetch(1);
self.channel.consume(queue.queue, (msg) => __awaiter(this, void 0, void 0, function* () {
yield handler(JSON.parse(msg.content.toString()));
self.channel.ack(msg);
}), { noAck: false });
});
}
}
exports.RabbitAdapter = RabbitAdapter;
//# sourceMappingURL=rabbitAdapter.js.map
;