Solve timeouts by touching analysis.json.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 15 Nov 2014 23:57:56 +0000 (00:57 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 16 Nov 2014 10:35:26 +0000 (11:35 +0100)
This means we need to carry fewer timeouts around, and also that
caching behavior in Varnish will be easier to control (results
are always cacheable, we don't need special handling for hanging ones).
It means slightly more thundering herd behavior, but we'll have that
anyway.

www/serve-analysis.js

index 4f0d2f0..362b14b 100644 (file)
@@ -17,9 +17,9 @@ var json_contents = undefined;
 var json_contents_gz = undefined;
 var json_last_modified = undefined;
 
-// The list of clients that are waiting for new data to show up,
-// and their associated timers. Uniquely keyed by request_id
-// so that we can take them out of the queue if they time out.
+// The list of clients that are waiting for new data to show up.
+// Uniquely keyed by request_id so that we can take them out of
+// the queue if they close the socket.
 var sleeping_clients = {};
 var request_id = 0;
 
@@ -27,6 +27,11 @@ var request_id = 0;
 // Used to show a viewer count to the user.
 var last_seen_clients = {};
 
+// The timer used to touch the file every 30 seconds if nobody
+// else does it for us. This makes sure we don't have clients
+// hanging indefinitely (which might have them return errors).
+var touch_timer = undefined;
+
 var reread_file = function(event, filename) {
        if (filename != path.basename(json_filename)) {
                return;
@@ -52,11 +57,19 @@ var reread_file = function(event, filename) {
                        });
                });
        });
+
+       if (touch_timer !== undefined) {
+               clearTimeout(touch_timer);
+       }
+       touch_timer = setTimeout(function() {
+               console.log("Touching analysis.json due to no other activity");
+               var now = Date.now() / 1000;
+               fs.utimes(json_filename, now, now);
+       }, 30000);
 }
 var possibly_wakeup_clients = function() {
        var num_viewers = count_viewers();
        for (var i in sleeping_clients) {
-               clearTimeout(sleeping_clients[i].timer);
                mark_recently_seen(sleeping_clients[i].unique);
                send_json(sleeping_clients[i].response,
                          sleeping_clients[i].accept_gzip,
@@ -91,11 +104,6 @@ var send_json = function(response, accept_gzip, num_viewers) {
        }
        response.end();
 }
-var timeout_client = function(client) {
-       mark_recently_seen(client.unique);
-       send_json(client.response, client.accept_gzip, count_viewers());
-       delete sleeping_clients[client.request_id];
-}
 var mark_recently_seen = function(unique) {
        if (unique) {
                last_seen_clients[unique] = (new Date).getTime();
@@ -163,11 +171,9 @@ server.on('request', function(request, response) {
        }
 
        // OK, so we need to hang until we have something newer.
-       // Put the user on the wait list; if we don't get anything
-       // in 30 seconds, though, we'll send something anyway.
+       // Put the user on the wait list.
        var client = {};
        client.response = response;
-       client.timer = setTimeout(function() { timeout_client(client); }, 30000);
        client.request_id = request_id;
        client.accept_gzip = accept_gzip;
        client.unique = unique;