From cf283895369412c1bfd7fdcda981f47a3c1bd4d0 Mon Sep 17 00:00:00 2001
From: Lloyd Hilaiel <lloyd@hilaiel.com>
Date: Tue, 22 May 2012 17:53:05 -0600
Subject: [PATCH] db.ping() must use the same application level query timing
 and reconnection logic as other query types - issue #1608

---
 lib/db/mysql_wrapper.js | 63 ++++++++++++++++++++++++++---------------
 1 file changed, 40 insertions(+), 23 deletions(-)

diff --git a/lib/db/mysql_wrapper.js b/lib/db/mysql_wrapper.js
index 45edfd7de..931ff97fb 100644
--- a/lib/db/mysql_wrapper.js
+++ b/lib/db/mysql_wrapper.js
@@ -39,14 +39,15 @@ exports.createClient = function(options) {
         logger.warn("database connection down: " + e.toString());
       });
     },
-    ping: function(cb) {
-      if (stalled) {
-        process.nextTick(function() {
-          cb("database is intentionally stalled");
-        });
-      } else {
-        this.realClient.ping(cb);
-      }
+    ping: function(client_cb) {
+      // ping queries are added to the front of the pending work queue.  they are
+      // a priority, as they are used by load balancers that want to know the health
+      // of the system.
+      queryQueue.unshift({
+        ping: true,
+        cb: client_cb
+      });
+      this._runNextQuery();
     },
     _runNextQuery: function() {
       var self = this;
@@ -93,25 +94,41 @@ exports.createClient = function(options) {
         }
       }, config.get('database.max_query_time_ms'));
 
-      this.realClient.query(work.query, work.args, function(err, r) {
-        // if we want to simulate a "stalled" mysql connection, we simply
-        // ignore the results from a query.
-        if (stalled) return;
+      if (work.ping) {
+        this.realClient.ping(function(err) {
+          if (stalled) {
+            return invokeCallback(work.cb, "database is intentionally stalled");
+          }
 
-        clearTimeout(slowQueryTimer);
-        slowQueryTimer = null;
-        consecutiveFailures = 0;
+          clearTimeout(slowQueryTimer);
+          slowQueryTimer = null;
+          consecutiveFailures = 0;
 
-        // report query time for all queries via statsd
-        var reqTime = new Date - work.startTime;
-        statsd.timing('query_time', reqTime);
+          invokeCallback(work.cb, err);
 
-        // report failed queries via statsd
-        if (err) statsd.increment('failed_query'); 
+          self._runNextQuery();
+        });
+      } else {
+        this.realClient.query(work.query, work.args, function(err, r) {
+          // if we want to simulate a "stalled" mysql connection, we simply
+          // ignore the results from a query.
+          if (stalled) return;
 
-        invokeCallback(work.cb, err, r);
-        self._runNextQuery();
-      });
+          clearTimeout(slowQueryTimer);
+          slowQueryTimer = null;
+          consecutiveFailures = 0;
+
+          // report query time for all queries via statsd
+          var reqTime = new Date - work.startTime;
+          statsd.timing('query_time', reqTime);
+
+          // report failed queries via statsd
+          if (err) statsd.increment('failed_query'); 
+
+          invokeCallback(work.cb, err, r);
+          self._runNextQuery();
+        });
+      }
     },
     query: function() {
       var client_cb;
-- 
GitLab