all files / app/bin/static/config/global/ 03_messaging.js

100% Statements 53/53
91.67% Branches 11/12
100% Functions 6/6
100% Lines 53/53
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71                 312× 312× 312× 624× 624×                    
var path = require('path')
var logger = require(path.join('yaktor', 'logger'))
logger.info(__filename)
var messageService = require(path.join('yaktor', 'services', 'messageService'))
var dns = require('dns')
var os = require('os')
var zmq = require('zmq')
var pub = zmq.socket('pub')
var sub = zmq.socket('sub')
var util = require('util')
 
var sequence = Number.MAX_SAFE_INTEGER
 
var EventEmitter = require('events').EventEmitter
var emitter = new EventEmitter()
emitter.setMaxListeners(0)
var oEmit = emitter.emit.bind(emitter)
 
module.exports = function (config, done) {
  var knownPeers = config.messaging.peers = {}
  dns.lookup(os.hostname(), function (ignoreError, myIp) {
    sub.on('message', function (foreignAddress, foreignSequence, topic, message) {
      foreignSequence = parseInt(foreignSequence, 32)
      var expectedSequence = knownPeers[foreignAddress] ++
      if (expectedSequence !== foreignSequence) {
        // TODO notify clients
        logger.error('sequence inversion: %s expected %s got %s', foreignAddress, expectedSequence, foreignSequence)
        knownPeers[foreignAddress] = foreignSequence + 1
      }
      if (!Number.isSafeInteger(knownPeers[foreignAddress])) {
        knownPeers[foreignAddress] = 0
      }
      oEmit(topic, JSON.parse(message))
    })
 
    var find = function () {
      dns.lookup(config.stack, { all: true }, function (ignoreError, peers) {
        var subUrl
        for (var p in peers) {
          var address = peers[p].address
          if (myIp !== address && !knownPeers.hasOwnProperty(address)) {
            knownPeers[address] = Number.MAX_SAFE_INTEGER
            subUrl = util.format(config.messaging.url, address, config.messaging.port)
            sub.subscribe(address)
            sub.connect(subUrl)
            logger.debug('messaging connected to', subUrl)
          }
        }
      })
    }
    Eif (config.log.level === 'silly') {
      sub.monitor(1)
      sub.on('connect', logger.silly.bind(logger, 'connect'))
      sub.on('disconnect', logger.silly.bind(logger, 'disconnect'))
    }
    find()
    setInterval(find, config.messaging.updateIntervalMillis)
    emitter.emit = function (topic, message) {
      pub.send([myIp, (sequence++).toString(32), topic, JSON.stringify(message)])
      if (!Number.isSafeInteger(sequence)) {
        sequence = 0
      }
      oEmit(topic, message)
    }
    messageService.emitter = emitter
    var pubUrl = util.format(config.messaging.url, myIp, config.messaging.port)
    pub.bind(pubUrl, done)
    logger.debug('messaging bound to', pubUrl)
  })
}