Skip to content

client SYNC_CONNECTED despite being disconnected from the server for longer than session timeout #13

@emiloslavsky

Description

@emiloslavsky

Client stays in SYNC_CONNECTED state when disconnected from the server for longer than its session timeout. I expected DISCONNECTED state after second 3 or 5 below:

$ node watch.js 127.0.0.1:2181 /blah/eph3 bomb& sleep 1; sudo disable_port 2181 10;
[1] 29292
[ '127.0.0.1:2181', '/blah/eph3' ]
0: client is DISCONNECTED[0]
"connected" to the server.
[ 'client state', { name: 'SYNC_CONNECTED', code: 3 } ]
Node: /blah/eph3 is successfully created.
zk.exists@/blah/eph3 [path, result, error, stat] ["/blah/eph3",0,null,{"specification":[{"name":"czxid","type":"long"},{"name":"mzxid","type":"long"},{"name":"ctime","type":"long"},{"name":"mtime","type":"long"},{"name":"version","type":"int"},{"name":"cversion","type":"int"},{"name":"aversion","type":"int"},{"name":"ephemeralOwner","type":"long"},{"name":"dataLength","type":"int"},{"name":"numChildren","type":"int"},{"name":"pzxid","type":"long"}],"czxid":[0,0,0,0,0,0,10,41],"mzxid":[0,0,0,0,0,0,10,41],"ctime":[0,0,1,65,127,31,233,184],"mtime":[0,0,1,65,127,31,233,184],"version":0,"cversion":0,"aversion":0,"ephemeralOwner":[1,65,96,50,23,73,0,51],"dataLength":4,"numChildren":0,"pzxid":[0,0,0,0,0,0,10,41]}]
1: client is SYNC_CONNECTED[3]
2: client is SYNC_CONNECTED[3]
3: client is SYNC_CONNECTED[3]
4: client is SYNC_CONNECTED[3]
5: client is SYNC_CONNECTED[3]
6: client is SYNC_CONNECTED[3]
7: client is SYNC_CONNECTED[3]
8: client is SYNC_CONNECTED[3]
9: client is SYNC_CONNECTED[3]
10: client is SYNC_CONNECTED[3]
11: client is SYNC_CONNECTED[3]
12: client is SYNC_CONNECTED[3]
zk watcher@/blah/eph3: NODE_DELETED[2]@/blah/eph3 state SYNC_CONNECTED[3]
zk.exists@/blah/eph3 [path, result, error, stat] ["/blah/eph3",-4,"Exception: CONNECTION_LOSS[-4]",null]
[ 'client state', { name: 'DISCONNECTED', code: 0 } ]
[ 'client state', { name: 'EXPIRED', code: -122 } ]
close1
[ 'client state', { name: 'DISCONNECTED', code: 0 } ]
13: client is DISCONNECTED[0]
14: client is DISCONNECTED[0]
15: client is DISCONNECTED[0]
$ cat watch.js
var zookeeper = require('node-zookeeper-client');
function inspect(o) { return require('util').inspect(o, false, null); }

console.dir([process.argv[2], process.argv[3]]);
var client = zookeeper.createClient(process.argv[2], {retries: 0, sessionTimeout: 5000});
var path = process.argv[3];
var data = new Buffer(process.argv[4]);

function exceptionObjectToCode(exceptionObject) { return exceptionObject ? exceptionObject.getCode() : zookeeper.Exception.OK; }
function exceptionObjectToString(exceptionObject) { return exceptionObject ? exceptionObject.toString() : null; }

client.on('state', function (s) {
   console.dir(['client state', s]);
   if (client.getState() === zookeeper.State.EXPIRED) {
     console.log('close1');
     client.close();
   }
});

function curryExistsHandler(path, next) {
  return function (exceptionObject, stat) {
    var rc = exceptionObjectToCode(exceptionObject); 
    var error = exceptionObjectToString(exceptionObject);
    console.log("zk.exists@" + path + " [path, result, error, stat] " + JSON.stringify([path, rc, error, stat]));
    return next(null);
  };
}
function watcherCallback(watcherEvent) {
  var type = watcherEvent.getType();
  var path = watcherEvent.getPath();
  console.log('zk watcher@' + path + ': ' + watcherEvent.toString() + ' state ' + client.getState());
  client.exists(path, watcherCallback,
    curryExistsHandler(path,
      function(nextError) {
        if (nextError) {
          console.log('exists callback throwing ' + inspect(nextError));
          throw nextError;
        }
      }));
}

client.once('connected', function () {
    console.log('"connected" to the server.');
    client.create(path,  new Buffer('blah'), zookeeper.ACL.OPEN_ACL_UNSAFE, 
      zookeeper.CreateMode.EPHEMERAL,
      function (error) {
        if (error) {
            console.log('Failed to create node: %s due to: %s.', path, error);
        } else {
            console.log('Node: %s is successfully created.', path);
        }

        client.exists(path, watcherCallback, curryExistsHandler(path,
              function(nextError) {
                if (nextError) {
                  console.log('exists (top) callback throwing ' + inspect(nextError));
                  throw nextError;
                }
              }));
    });
});
client.connect();

var startTime = Date.now();
function reportClientStateLoop() {
  console.log(Math.round((Date.now()-startTime)/1000) + ': client is ' + client.getState());
  setTimeout(reportClientStateLoop, 1000);
}
reportClientStateLoop();

$ cat disable_port
/bin/bash -c "/sbin/iptables -I INPUT 1 -p tcp --sport ${1} -j DROP; /sbin/iptables -I INPUT 2 -p tcp --dport ${1} -j DROP; sleep ${2}; /sbin/iptables -D INPUT 1; /sbin/iptables -D INPUT 1"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions