UNPKG

iamqp

Version:

RabbitMQ wrapper for NodeJS with several produce(reply)/consume scenarios

229 lines (196 loc) 12 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>rpc/rpc_server.js - Documentation</title> <script src="scripts/prettify/prettify.js"></script> <script src="scripts/prettify/lang-css.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav> <li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Common.html">Common</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Common.html#_commonPublishPreparations">_commonPublishPreparations</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Common.html#_emitAndDispatchError">_emitAndDispatchError</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Common.html#_logData">_logData</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Common.html#_messageDispatcherWrapper">_messageDispatcherWrapper</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Common.html#_parseConsumedMessage">_parseConsumedMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Common.html#_preparePublishingMessage">_preparePublishingMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Common.html#closeConnection">closeConnection</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Common.html#getEventer">getEventer</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Common.html#isReady">isReady</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Common.html#openConnection">openConnection</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Common.html#toString">toString</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="ConsoleLogger.html">ConsoleLogger</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ConsoleLogger.html#error">error</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ConsoleLogger.html#info">info</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ConsoleLogger.html#log">log</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ConsoleLogger.html#warn">warn</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="FanoutConsumer.html">FanoutConsumer</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="FanoutProducer.html">FanoutProducer</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="FanoutProducer.html#fanout">fanout</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="PlainConsumer.html">PlainConsumer</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="PlainProducer.html">PlainProducer</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="PlainProducer.html#publish">publish</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="RpcClient.html">RpcClient</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="RpcClient.html#callRemote">callRemote</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="RpcServer.html">RpcServer</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="RpcServer.html#respond">respond</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="UUIDv4.html">UUIDv4</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="UUIDv4.html#generate">generate</a></span></li><li class="nav-heading"><a href="global.html">Globals</a></li> </nav> <div id="main"> <h1 class="page-title">rpc/rpc_server.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>const MESSAGES = require('../internal').MESSAGES const _get = require('lodash/get') const _isString = require('lodash/isString') /** * RPC server. Init example: * &lt;pre> * const iamqp = require('iamqp'); * const amqpUri = 'amqp://localhost'; * const rpcChannel = 'rpc-channel-a'; * let rpcServer = new iamqp.RPCServer(amqpUri, rpcChannel); * * // This needs to be done or the errors will bubble up. * rpcServer.getEventer().on('error', (err) => { * console.log('RPC server error:' + err.message); * }); * * // For when the connection is established. * rpcServer.getEventer().on('connected', () => { * console.log('RPC server connected'); * }); * * // An event gets emitted on each call. * // Handling of the pCorrelationId is optional and should be done only if you expect a single RPC server instance * // to handle multiple RPC clients. * // For example if the RPC server interacts with a DB on the behalf of the client and the calls are just * // coming in. * // This means that you can parameters pCorrelationId in both receiving the call and responding. * rpcServer.getEventer().on('call', (callData, pCorrelationId) => { * console.log('RPC server got a call: ' + callData); * * // ... * * let isServerResponding = rpcServer.respond({ * 'a': 3 * }, pCorrelationId); * }); * * // Open the connection - this takes some time and is not sync * rpcServer.openConnection(); * * // ... * * // Close the connection * if (rpcServer.closeConnection()) { * console.log('RPC server connection closing ...'); * } * &lt;/pre> * ... */ class RpcServer extends require('../common') { /** * @param {AmqpURI} amqpUri * @param {ChannelName} channelName * @param {Configuration} [configuration] */ constructor (amqpUri, channelName, configuration) { super(amqpUri, channelName, configuration) this._name = `RPC-SERVER: ${this._configuration.channelName}` this._messageDispatcherWrapper('info', MESSAGES.INIT) this._lastMessage = null this._calls = {} this._E.on('connected', () => { this._createChannel() }) } /** * Create the channel. * @private */ _createChannel () { this._amqp.connection.createChannel((channelCreatingErr, createdChannel) => { if (channelCreatingErr) { this._emitAndDispatchError(`${MESSAGES.CHANNEL_ERROR} -> ${channelCreatingErr.message}`) return } this._messageDispatcherWrapper('info', `${MESSAGES.CHANNEL_READY} -> ${MESSAGES.QUEUE_ASSERTING} -> ${MESSAGES.BINDING_CONSUMER_FUNCTION}`) this._lastMessage = null this._amqp.channel = createdChannel this._amqp.channel.assertQueue(this._configuration.channelName, { durable: false, arguments: _get(this._configuration, 'configuration.queueArguments', {}) }) // this._amqp.channel.prefetch(1); this._amqp.channel.consume(this._configuration.channelName, (data) => { if ( data &amp;&amp; _get(data, 'properties.replyTo', null) &amp;&amp; _get(data, 'properties.correlationId', null) ) { this._calls[data.properties.correlationId] = data this._lastMessage = data this._E.emit('call', this._parseConsumedMessage(data), data.properties.correlationId) } else { this._lastMessage = null this._messageDispatcherWrapper('error', `${MESSAGES.GOT_MESSAGE} -> ${MESSAGES.INVALID_PROPERTY}`) } }, { noAck: false }) }) } /** * Respond to the last call/message. * @param {number | string | boolean | Object | Array} contentToPublish * @param {string} correlationId correlation ID (as gotten from the call) parameter to use when the server * is to process multiple calls at once * @returns {boolean} */ respond (contentToPublish, correlationId) { if (this._isReady === true) { let lastMessage = null let isFromCallsStorage = false if (correlationId) { if ( _isString(correlationId) &amp;&amp; Object.prototype.hasOwnProperty.call(this._calls, correlationId) ) { lastMessage = this._calls[correlationId] isFromCallsStorage = true } else { this._messageDispatcherWrapper('error', 'attempting to respond with an invalid correlation ID') return false } } else if (this._lastMessage) { lastMessage = this._lastMessage } if ( !lastMessage || !_get(lastMessage, 'properties.replyTo', null) || !_get(lastMessage, 'properties.correlationId', null) ) { this._messageDispatcherWrapper('error', 'attempting to respond to an invalid message') return false } this._amqp.channel.sendToQueue( lastMessage.properties.replyTo, this._preparePublishingMessage(contentToPublish), { correlationId: lastMessage.properties.correlationId } ) this._amqp.channel.ack(lastMessage) process.nextTick(() => { delete this._calls[lastMessage.properties.correlationId] if (!isFromCallsStorage) { this._lastMessage = null } }) return true } else { this._messageDispatcherWrapper('error', `${MESSAGES.RESPOND} -> ${MESSAGES.CONNECTION_ERROR}`) return false } } } module.exports = RpcServer </code></pre> </article> </section> </div> <br class="clear"> <footer> Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.2</a> on Sun Aug 04 2019 22:10:47 GMT+0200 (Central European Summer Time) using the Minami theme. </footer> <script>prettyPrint();</script> <script src="scripts/linenumber.js"></script> </body> </html>