UNPKG

@stoplight/moleculer

Version:

Fast & powerful microservices framework for Node.JS

216 lines (183 loc) 5.22 kB
/* * moleculer * Copyright (c) 2019 MoleculerJS (https://github.com/moleculerjs/moleculer) * MIT Licensed */ "use strict"; const Transporter = require("./base"); const { PACKET_REQUEST, PACKET_EVENT } = require("../packets"); /** * Transporter for NATS Streaming server * * More info: http://nats.io/ * * @class StanTransporter * @extends {Transporter} */ class StanTransporter extends Transporter { /** * Creates an instance of StanTransporter. * * @param {any} opts * * @memberof StanTransporter */ constructor(opts) { if (typeof opts == "string") opts = { url: opts.replace("stan://", "nats://") }; super(opts); // Use the 'preserveBuffers' option as true as default if (!this.opts || this.opts.preserveBuffers !== false) { if (!this.opts) this.opts = {}; this.opts.preserveBuffers = true; } if (!this.opts.clusterID) this.opts.clusterID = "test-cluster"; // Default cluster ID in NATS Streaming server this.hasBuiltInBalancer = true; this.client = null; this.subscriptions = []; } /** * Connect to a NATS Streaming server * * @memberof StanTransporter */ connect() { return new this.broker.Promise((resolve, reject) => { let Stan; try { Stan = require("node-nats-streaming"); } catch (err) { /* istanbul ignore next */ this.broker.fatal( "The 'node-nats-streaming' package is missing! Please install it with 'npm install node-nats-streaming --save' command.", err, true ); } const client = Stan.connect(this.opts.clusterID, this.nodeID, this.opts); this._client = client; // For tests client.on("connect", () => { this.client = client; this.logger.info("NATS Streaming client is connected."); this.onConnected().then(resolve); }); /* istanbul ignore next */ client.on("reconnect", () => { this.logger.info("NATS Streaming client is reconnected."); this.onConnected(true); }); /* istanbul ignore next */ client.on("reconnecting", () => { this.logger.warn("NATS Streaming client is reconnecting..."); }); /* istanbul ignore next */ client.on("disconnect", () => { if (this.connected) { this.logger.warn("NATS Streaming client is disconnected."); this.connected = false; } }); /* istanbul ignore next */ client.on("error", e => { this.logger.error("NATS error.", e.message); this.logger.debug(e); if (!client.connected) reject(e); }); /* istanbul ignore next */ client.on("close", () => { this.connected = false; // Hint: It won't try reconnecting again, so we kill the process. this.broker.fatal("NATS Streaming connection closed."); }); }); } /** * Disconnect from a NATS Streaming server * * @memberof StanTransporter */ disconnect() { if (this.client) { this.client.close(); this.client = null; } } /** * Subscribe to a command * * @param {String} cmd * @param {String} nodeID * * @memberof StanTransporter */ subscribe(cmd, nodeID) { const t = this.getTopicName(cmd, nodeID); const opts = this.client.subscriptionOptions(); //.setStartWithLastReceived().setDurableName(cmd); //No need durable & receive old messages const subscription = this.client.subscribe(t, opts); subscription.on("message", msg => this.receive(cmd, msg.getRawData())); return this.broker.Promise.resolve(); } /** * Subscribe to balanced action commands * * @param {String} action * @memberof StanTransporter */ subscribeBalancedRequest(action) { const topic = `${this.prefix}.${PACKET_REQUEST}B.${action}`; const queue = action; const opts = this.client .subscriptionOptions() .setDeliverAllAvailable() .setDurableName(PACKET_REQUEST + "B"); const subscription = this.client.subscribe(topic, queue, opts); subscription.on("message", msg => this.receive(PACKET_REQUEST, msg.getRawData())); this.subscriptions.push(subscription); } /** * Subscribe to balanced event command * * @param {String} event * @param {String} group * @memberof StanTransporter */ subscribeBalancedEvent(event, group) { const topic = `${this.prefix}.${PACKET_EVENT}B.${group}.${event}`; const opts = this.client .subscriptionOptions() .setDeliverAllAvailable() .setDurableName(PACKET_EVENT + "B"); const subscription = this.client.subscribe(topic, group, opts); subscription.on("message", msg => this.receive(PACKET_EVENT, msg.getRawData())); this.subscriptions.push(subscription); } /** * Unsubscribe all balanced request and event commands * * @memberof BaseTransporter */ unsubscribeFromBalancedCommands() { return new this.broker.Promise(resolve => { this.subscriptions.forEach(sub => sub.unsubscribe()); this.subscriptions = []; //this.client.flush(resolve); resolve(); }); } /** * Send data buffer. * * @param {String} topic * @param {Buffer} data * @param {Object} meta * * @returns {Promise} */ send(topic, data) { /* istanbul ignore next*/ if (!this.client) return this.broker.Promise.resolve(); return new this.broker.Promise(resolve => { this.client.publish(topic, data, resolve); }); } } module.exports = StanTransporter;