Revision: e33b86b78b05
Author:   gdusbabek <gdusba...@gmail.com>
Date:     Fri Dec 16 06:12:33 2011
Log: Move the timeout logic into the calls themselves. I think this simplifies the logic by avoiding the layering and indirection introduced by the wrapping approach.

http://code.google.com/a/apache-extras.org/p/cassandra-node/source/detail?r=e33b86b78b05

Deleted:
 /lib/util.js
Modified:
 /lib/driver.js

=======================================
--- /lib/util.js        Tue Nov 29 04:11:51 2011
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * Wrap a function so that the original function will only be called once,
- * regardless of how  many times the wrapper is called.
- * @param {Function} fn The to wrap.
- * @return {Function} A function which will call fn the first time it is called.
- */
-exports.fireOnce = function fireOnce(fn) {
-  var fired = false;
-  return function wrapped() {
-    if (!fired) {
-      fired = true;
-      fn.apply(null, arguments);
-    }
-  };
-};
=======================================
--- /lib/driver.js      Tue Nov 29 04:11:51 2011
+++ /lib/driver.js      Fri Dec 16 06:12:33 2011
@@ -30,7 +30,6 @@
 var async = require('async');
 var Cassandra = require('./gen-nodejs/Cassandra');
 var ttypes = require('./gen-nodejs/cassandra_types');
-var util = require('./util');

 var genericPool = require('generic-pool');

@@ -53,7 +52,7 @@
 var DEFAULT_STEP_TIMEOUTS = {
   'login': 1000,
   'learn': 2000,
-  'use': 1000,
+  'use': 1000
 };

 /** converts object to a string using toString() method if it exists. */
@@ -392,15 +391,29 @@
   this.con.on('connect', function() {
     clearTimeout(timeoutId);

+    function decorateErrWithErrno(err, errno) {
+      err.errno = errno;
+      return err;
+    }
+
     // preparing the conneciton is a 3-step process.

     // 1) login
     var login = function(cb) {
       if (self.connectionInfo.user || self.connectionInfo.pass) {
var creds = new ttypes.AuthenticationRequest({user: self.connectionInfo.user, password: self.connectionInfo.pass});
+        var sentinel = setTimeout(function() {
+          if (sentinel) {
+            sentinel = null;
+ cb(decorateErrWithErrno(new Error('login timed out'), constants.ETIMEDOUT));
+          }
+        }, DEFAULT_STEP_TIMEOUTS.login);
         self.client.login(creds, function(err) {
-          if (err) { amendError(err); }
-          cb(err);
+          if (sentinel) {
+            sentinel = clearTimeout(sentinel);
+            if (err) { amendError(err); }
+            cb(err);
+          }
         });
       } else {
         cb(null);
@@ -409,85 +422,66 @@

     // 2) login.
     var learn = function(cb) {
+      var sentinel = setTimeout(function() {
+        if (sentinel) {
+          sentinel = null;
+ cb(decorateErrWithErrno(new Error('learn timed out'), constants.ETIMEDOUT));
+        }
+      }, DEFAULT_STEP_TIMEOUTS.learn);
self.client.describe_keyspace(self.connectionInfo.keyspace, function(err, def) {
-        if (err) {
-          amendError(err);
-          cb(err);
-        } else {
-          for (var i = 0; i < def.cf_defs.length; i++) {
-            var validators = {
-              key: def.cf_defs[i].key_validation_class,
-              comparator: def.cf_defs[i].comparator_type,
-              defaultValidator: def.cf_defs[i].default_validation_class,
-              specificValidators: {}
-            };
- for (var j = 0; j < def.cf_defs[i].column_metadata.length; j++) { - // todo: verify that the name we use as the key represents the raw-bytes version of the column name, not
-              // the stringified version.
- validators.specificValidators[def.cf_defs[i].column_metadata[j].name] = def.cf_defs[i].column_metadata[j].validation_class;
-            }
-            self.validators[def.cf_defs[i].name] = validators;
-          }
-          cb(null); // no errors.
+        if (sentinel) {
+          sentinel = clearTimeout(sentinel);
+          if (err) {
+            amendError(err);
+            cb(err);
+          } else {
+            for (var i = 0; i < def.cf_defs.length; i++) {
+              var validators = {
+                key: def.cf_defs[i].key_validation_class,
+                comparator: def.cf_defs[i].comparator_type,
+                defaultValidator: def.cf_defs[i].default_validation_class,
+                specificValidators: {}
+              };
+ for (var j = 0; j < def.cf_defs[i].column_metadata.length; j++) { + // todo: verify that the name we use as the key represents the raw-bytes version of the column name, not
+                // the stringified version.
+ validators.specificValidators[def.cf_defs[i].column_metadata[j].name] = def.cf_defs[i].column_metadata[j].validation_class;
+              }
+              self.validators[def.cf_defs[i].name] = validators;
+            }
+            cb(null); // no errors.
+          }
         }
       });
     };

     // 3) set the keyspace on the server.
     var use = function(cb) {
+      var sentinel = setTimeout(function() {
+        sentinel = null;
+ cb(decorateErrWithErrno(new Error('use timed out'), constants.ETIMEDOUT));
+      }, DEFAULT_STEP_TIMEOUTS.use);
+
self.client.set_keyspace(self.connectionInfo.keyspace, function(err) {
-        if (err) { amendError(err); }
-        cb(err);
+        if (sentinel) {
+          sentinel = clearTimeout(sentinel);
+          if (err) { amendError(err); }
+          cb(err);
+        }
       });
     };

-    async.series([
-      function loginStep(callback) {
- var wrappedCallback = wrapStepCallback('login', DEFAULT_STEP_TIMEOUTS.login, callback);
-        login(wrappedCallback);
-      },
-
-      function learnStep(callback) {
- var wrappedCallback = wrapStepCallback('learn', DEFAULT_STEP_TIMEOUTS.learn, callback);
-        learn(wrappedCallback);
-      },
-
-      function useStep(callback) {
- var wrappedCallback = wrapStepCallback('use', DEFAULT_STEP_TIMEOUTS.use, callback);
-        use(wrappedCallback);
-      },
-    ],
-
-    function(err) {
-      if (err) {
-        self.close();
-      }
-
-      callback(err);
-    });
+    async.series(
+      [login, learn, use],
+      function(err) {
+        if (err) {
+          self.close();
+        }
+        callback(err);
+      }
+    );
   });

-  function timeoutStep(name, timeout, callback) {
-    var timeoutId = setTimeout(function stepTimeoutHandler() {
-      var err = new Error('Step "' + name + '" timed out.');
-      err.errno = constants.ETIMEDOUT;
-
-      callback(err);
-    }, timeout);
-
-    return timeoutId;
-  }
-
-  function wrapStepCallback(name, timeout, callback) {
-    callback = util.fireOnce(callback);
-    var timeoutId = timeoutStep(name, timeout, callback);
-
-    return function wrappedCallback(err) {
-      clearTimeout(timeoutId);
-      callback(err);
-    };
-  }
-
   function connectTimeout() {
     var err = new Error('ETIMEDOUT, Operation timed out');
     err.errno = constants.ETIMEDOUT;

Reply via email to