how do I get a ROUTER -> DEALER to echo?

I'm trying to build the back half of a Paranoid Pirate Pattern, a ROUTER that sends work out to a set of DEALER nodes (it's possible that I'm misundertanding the diagram). For now I just want the DEALERs to echo the work back or just send back a message that says "done". The problem is that the worker node (DEALER) is never receiving any messages.

var buildSocket, connectionTemplate, delay, frontPort, log, q, qPort, worker, workerPort, zmq;

zmq = require("zmq");    
frontPort = 5000;    
qPort = 5100;    
workerPort = 5200;    
connectionTemplate = "tcp://127.0.0.1:";    
log = console.log;    
debugger;    
delay = process.argv[2] || 1000;

buildSocket = function(desc, socketType, port) {
  var socket;
  log("creating " + socketType + " socket");
  socket = zmq.socket(socketType);
  socket.identity = "" + desc + "-" + socketType + "-" + process.pid + "-" + port;
  return socket;
};

q = buildSocket('q_output', 'router', qPort);

worker = buildSocket('worker', 'dealer', workerPort);

worker.bind("" + connectionTemplate + workerPort);

q.connect("" + connectionTemplate + workerPort);

q.on('message', function() {
  var args;
  args = Array.apply(null, arguments);
  log('queue received ' + JSON.stringify(arguments));
  return worker.send('work done');
});

worker.on('message', function() {
  var args;
  log('back received ' + JSON.stringify(arguments));
  args = Array.apply(null, arguments);
  return q.send(args);
});

setInterval((function() {
  var value;
  value = Math.floor(Math.random() * 100);
  console.log(q.identity + ": sending " + value);
  q.send(value);
}), delay);

The queue and worker on 'message' events never fire. The way I understand this is you set up the ROUTER node, bind it to a port (for return messages), set up the DEALER nodes and bind them to a port then connect the ROUTER to the DEALER port and start sending messages. In practice, messages are sent but never received:

creating router socket
creating dealer socket
q_output-router-60326-5100: sending 30
q_output-router-60326-5100: sending 25
q_output-router-60326-5100: sending 65
q_output-router-60326-5100: sending 68
q_output-router-60326-5100: sending 50
q_output-router-60326-5100: sending 88

You've got things a little backwards, here. Think of a DEALER socket as a modified REQ socket... it should be initiating your messages to your router. A ROUTER socket is more like a modified REP socket... it should be responding to the initial request sent by your dealer.

You don't strictly need to follow that pattern with ROUTER/DEALER pairings... but it definitely makes things much easier, so you should stick with it while you're learning.

The second thing that sticks out to me from your code is that you message handlers, you've got the wrong socket sending messages.

Take for instance this code (directly copied without modification):

q.on('message', function() {
  var args;
  args = Array.apply(null, arguments);
  log('queue received ' + JSON.stringify(arguments));
  return worker.send('work done');
});

... that says (in psuedocode):

when `q` receives a message from `worker`
  print out the message we received
  now have `worker` send *another* message that says "work done"

What you want is something more like the following (simplified):

var zmq = require("zmq");
var q = zmq.socket('router');
var worker = zmq.socket('dealer');

// I've switched it so the router is binding and the worker is connecting
// this is somewhat arbitrary, but generally I'd consider workers to be less
// reliable, more transient, and also more numerous. I'd think of the queue
// as the "server"

// I've used bindSync, which is synchronous, but that's typically OK in the
// startup phase of a script, and it simplifies things.  If you're spinning
// up new sockets in the middle of your script, using the async bind()
// is more appropriate
q.bindSync('tcp://127.0.0.1:5200');

worker.connect('tcp://127.0.0.1:5200');

q.on('message', function() {
  var args;
  args = Array.apply(null, arguments);
  log('queue received ' + JSON.stringify(arguments));

  // if we've received a message at our queue, we know the worker is ready for
  // more work, so we ready some new data, regardless of whether we
  // received work back
  var value = Math.floor(Math.random() * 100);

  // note that the socket that received the message is responding back
  if (args[1].toString() == 'ready') console.log('worker now online');
  else console.log('work received: '+args[1].toString());

  // we need to specify the "ID" of our worker as the first frame of
  // the message
  q.send([args[0], value]);

  // we don't need to return anything, the return value of a
  // callback is ignored
});

worker.on('message', function() {
  var args;
  log('back received ' + JSON.stringify(arguments));
  args = Array.apply(null, arguments);

  // we're just echoing back the "work" we received from the queue
  // for additional "workiness", we wait somewhere between 10-1000
  // milliseconds to respond
  setTimeout(function() {
    worker.send(args[0].toString());
  }, parseInt(args[0].toString())*10);
});

setTimeout((function() {
  var value;
  console.log('WORKER STARTING UP');

  // the worker starts the communication, indicating it's ready
  // rather than the queue just blindly sending work
  worker.send('ready'); // sending the first message, which we catch above
}), 500); // In my experience, half a second is more than enough, YMMV

... as you can see, the pattern is:

  1. Worker indicates readiness
  2. Queue sends available work
  3. Worker completes work and sends back
  4. Queue receives completed work and sends back more work
  5. GOTO 3