oortcloud / node-ddp-client

A callback style DDP (Meteor's Distributed Data Protocol) node client.
Other
263 stars 80 forks source link

Callback never called #84

Open oreynaldocl opened 8 years ago

oreynaldocl commented 8 years ago

Hello. I found an interesting problem. It only happened when I debugged my code. If for some reason I lose the connection of DDP(not closed or error) if I call .subscribe or .call the callback is never called. Debugging I lost the connection because the socket can't resolve ping-pong process and it set its readyState to 2 I debugged really deep and I found this code

// .../node_modules/ddp/lib/ddp-client.js
DDPClient.prototype.subscribe = function(name, params, callback) {
  ...
  self._callbacks[id] = callback;
  ...
  self._send({
    msg    : "sub",
    ...
  });
};
DDPClient.prototype._send = function(data) {
  this.socket.send(
    EJSON.stringify(data)
  );
};

// .../node_modules/ddp/node_modules/faye-websocket/lib/faye/websocket/api.js
  send: function(data) {
    if (this.readyState > API.OPEN) return false;
    if (!(data instanceof Buffer)) data = String(data);
    return this._driver.messages.write(data);
  },

This condition if (this.readyState > API.OPEN) is true and the socket never sends the message but the DDP added the callback but it never has an answer message for this callback and it will been waiting forever for this callback.

Without debugging this error never happens, but I think is really dangerous that the DDP don't manage this problem, it can happen and the DDP will wait forever.

Anybody had this problem?

sebakerckhof commented 8 years ago

It's up to you to discover lost connections.

oreynaldocl commented 8 years ago

Ok, I am adding connection states controls. This also happen if the process is busy and the connection is lost.

sebakerckhof commented 8 years ago

DDP does specify a ping/pong mechanism you can leverage for this

oreynaldocl commented 8 years ago

Yep, I am testing and the connection is always recovered, that is a great feature. But I need to add a control to avoid perform an action (call, subscribe, close) if the connection is recovering.

I checked the code and the action is never sent if the connection is recovering and DDP doesn't have a way to retry the action.

ghost commented 7 years ago

This is really nasty stuff, I get connection lost every time I call particular method. Method always successfully work on server but then callback never return because connection silently get down. When on timeout I make ddpclient.close and then .connect, randomly every 40-90 seconds I get socket-close event firing, so connection closing and then recovering and then closing, infinitely.