tristanls / discover

Node discovery based on Kademlia DHT protocol.
MIT License
69 stars 10 forks source link

Discover Usage #11

Closed skeggse closed 10 years ago

skeggse commented 10 years ago

I've been trying to get discover running, and I think that some of my expectations about how discover works/should work are getting in the way of my understanding how it does work.

I'm also lamenting the lack of a clear end-to-end usage example.

var Discover = require('discover');
var Transport = require('discover-tcp-transport');
var crypto = require('crypto');

function arbiter(incumbent, candidate) {
  if (!incumbent || !incumbent.workerNodes)
    return candidate;

  if (!candidate || !candidate.workerNodes)
    return incumbent;

  var merged = {
    id: incumbent.id, // incumbent.id === candidate.id within an arbiter
    workerNodes: incumbent.workerNodes
  };

  for (var id in candidate.workerNodes) {
    var incumbentClock = incumbent.workerNodes[id].vectorClock;
    var candidateClock = candidate.workerNodes[id].vectorClock;
    if (candidateClock >= incumbentClock) {
      merged.workerNodes[id] = candidate.workerNodes[id];
    }
  }

  return merged;
}

function arbiterDefaults(contact) {
  if (!contact.data)
    contact.data = {};
  else if (!contact.data.workerNodes)
    contact.data.workerNodes = {};
  else {
    var workers = contact.data.workerNodes;
    for (var key in workers) {
      if (!workers[key].vectorClock) {
        workers[key].vectorClock = 0;
      }
    }
  }
  return contact;
}

var primary = process.argv[2] === 'primary';

var id = crypto.randomBytes(20).toString('base64');
console.log('worker', id);

var transport = new Transport({port: primary ? 9000 : 9001});

var options = {
  arbiter: arbiter,
  arbiterDefaults: arbiterDefaults,
  transport: transport
};

if (!primary) {
  options.seeds = [{
    id: new Buffer('hmmm'),
    transport: {
      host: '127.0.0.1',
      port: 9000
    }
  }];
}

var discover = new Discover(options);

transport.listen();

var workers = {};
workers[id] = {
  host: '127.0.0.1',
  port: primary ? 8000 : 8001
};

discover.register({
  id: new Buffer('UserService').toString('base64'),
  data: {
    workerNodes: workers
  }
});

if (!primary) {
  setTimeout(function() {
    discover.find(new Buffer('UserService').toString('base64'), function(err, contact) {
      if (err)
        return console.log('error', err.stack);
      console.log(require('util').inspect(contact, {depth: null, colors: true}));
    });
  }, 1000);
}
$ node discover-test primary &
worker 4oMG5JHBOIUELmSbR8X6tgzlq5o=
$ node discover-test secondary
worker yZ4NEadKOCpHfrt+ENnSSFL0vnY=
{ id: 'VXNlclNlcnZpY2U=',
  data: 
   { workerNodes: 
      { 'yZ4NEadKOCpHfrt+ENnSSFL0vnY=': 
         { host: '127.0.0.1',
           port: 8001,
           vectorClock: 0 } } },
  transport: { host: 'localhost', port: 9001 } }

I'm expecting the find to give me a merged object, and I'm expecting the arbiter to be called sometime, but that's not happening. What am I doing wrong?

skeggse commented 10 years ago

If you're interested, I ended up building a module called solidipes which provides rapid node and service discovery.