@betit/orion
Version:
Pluggable microservice framework
171 lines (170 loc) • 4.61 kB
JavaScript
;
const nats = require('nats');
const utils_1 = require('../utils');
const debug = utils_1.debugLog('orion:transport:nats');
/**
* NATS transport.
*/
class NatsTransport {
/**
* Create new NATS transport.
*/
constructor(options) {
this.options = options;
this.options = Object.assign({
url: process.env.NATS || 'nats://localhost:4222',
encoding: 'binary'
}, options);
this.client = nats.connect(this.options);
this.client.on('error', function (e) {
debug(e);
process.exit();
});
this.heartbeat();
}
/**
* NATS heartbeat check based on
* https://github.com/nats-io/node-nats/issues/173
*/
heartbeat() {
let timeout = null;
setInterval(() => {
timeout = setTimeout(() => {
timeout = null;
}, 500);
this.listen(() => {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
});
}, 1000);
}
/**
* Transport listen.
*/
listen(callback) {
try {
this.client.flush((err) => {
if (err) {
throw err;
}
if (callback && callback instanceof Function) {
callback();
}
});
}
catch (e) {
if (e.code === nats.CONN_CLOSED && this.closeHandler) {
this.closeHandler();
}
throw e;
}
}
/**
* Publish to a topic.
*/
publish(topic, message) {
try {
this.client.publish(topic, message);
}
catch (e) {
if (e.code === nats.CONN_CLOSED && this.closeHandler) {
this.closeHandler();
}
throw e;
}
}
/**
* Subscribe to a topic.
*/
subscribe(topic, group, callback) {
try {
return this.client.subscribe(topic, { queue: group }, callback);
}
catch (e) {
if (e.code === nats.CONN_CLOSED && this.closeHandler) {
this.closeHandler();
}
throw e;
}
}
/**
* Unsubscribe from a topic.
*/
unsubscribe(sid, max) {
try {
this.client.unsubscribe(sid, max);
}
catch (e) {
if (e.code === nats.CONN_CLOSED && this.closeHandler) {
this.closeHandler();
}
throw e;
}
}
/**
* Transport handle.
*/
handle(route, group, callback) {
try {
debug('register handler:', route);
this.client.subscribe(route, { queue: group }, (req, replyTo) => {
debug('incoming request:', req, replyTo);
callback(req, res => {
debug('sending response:', replyTo, res);
this.client.publish(replyTo, res);
});
});
}
catch (e) {
if (e.code === nats.CONN_CLOSED && this.closeHandler) {
this.closeHandler();
}
throw e;
}
}
/**
* Client request.
* Nats client implements this pattern out of the box.
* Publish a request with an implicit inbox listener as the response.
* This should be treated as a subscription.
*/
request(route, payload, callback, timeout = 1000) {
try {
debug('sending request:', route);
const sid = this.client.request(route, payload, { max: 1 }, response => {
debug('got response:', response);
callback(response);
});
this.client.timeout(sid, timeout, 1, () => {
debug('request timeout:', route);
callback(new Error(`Transport timeout: ${route}`));
});
}
catch (e) {
if (e.code === nats.CONN_CLOSED && this.closeHandler) {
this.closeHandler();
}
throw e;
}
}
/**
* Close connection.
*/
close() {
this.client.close();
}
/**
* Connection closed handler
* @param {Function} callback
*/
onClose(callback) {
if (callback) {
this.closeHandler = callback;
this.client.on('close', callback);
}
}
}
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = NatsTransport;