UNPKG

axiom

Version:

Environment setup/runtime standardization for Node.js applications.

82 lines (64 loc) 2.38 kB
timers = require 'timers' _ = require 'lodash' bus = require '../bus' internal = require './internal' send = require './send' module.exports = (channel, data, done) -> core = require '../core' core.log.coreEntry 'request', {channel, data} # How many responders do we have responders = internal.responders[channel] or {} responderCount = _.keys(responders).length switch responderCount when 0 return done new Error "No responders for request: '#{channel}'" when 1 # Send the message replyTo = send channel, data else return done new Error "Ambiguous: #{responderCount} responders for request: '#{channel}'" # Define an 'onTimeout' callback for when we don't get a response # (either error or success) in the configured time. onTimeout = -> err = new Error "Request timed out on channel '#{channel}'" bus.publish channel: replyTo.channel topic: replyTo.topic.err data: err timeoutId = timers.setTimeout onTimeout, internal.config.timeout # Default callback is of signature (message, envelope). # Wrap so we can pass a conventional (err, result)-style callback. callback = (message, envelope) -> # We're done, so cancel timeouts and subscriptions. timers.clearTimeout timeoutId errSub.unsubscribe() successSub.unsubscribe() [condition, middle..., topicId] = envelope.topic.split('.') switch condition when 'err' done message when 'success' done null, message else # This should never be reached, as this callback should only # be invoked by a subscription to a topic of the form # 'err.<uuid>' or 'success.<uuid>'. err = new Error "Invalid condition '#{condition}' for response with topicId '#{topicId}'" done err # Subscribe to the 'err' response for topicId # We don't pass a callback immediately so that we can # refer to the subscription itself in the callback. errSub = bus.subscribe { channel: channel topic: replyTo.topic.err callback: callback } # Subscribe to the 'success' response for topicId # As above, we don't pass a callback immediately so that # we can refer to the subscription itself in the callback. successSub = bus.subscribe { channel: replyTo.channel topic: replyTo.topic.success callback: callback } return replyTo