Show:
/**
 *
 * Copyright 2013 Joel Grenon
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
(function() {
    var moment = require('moment');

    var WatchDog = (function(){

        /**
         * @class WatchDog
         * @protected
         * @description Each instance is responsible for monitoring the state of a single agent. If we don't receive heartbeat at regular intervals,
         * the watchdog will emit an agent-disconnected event to reset the agent communication.
         * @param agent {Object} An agent object (with id) to watch
         * @param dispatcher {Object} The dispatcher hosting this watchdog
         * @constructor
         */
        function WatchDog(agent, dispatcher) {
            var _this = this;

            var interval = agent.interval || 30;

            this.agent = agent;

            dispatcher.log.debug("Installing agent %s watchdog at an interval of %d seconds", agent.id, interval * 2);

            this.watchDogInterval = setInterval(function(){
                dispatcher.log.debug("Executing watchdog check for agent ", agent.id);

                dispatcher.db.multi()
                    .hget(agent.id, "lastHeartbeatTs")
                    .hget(agent.id, "status")
                    .exec(function(err, results) {
                        var delta;
                        dispatcher.log.trace(results, "Agent %s current state", agent.id);

                        try {
                            delta = moment().utc().unix() - moment(parseInt(results[0]) * 1000).utc().unix() + 5;
                        }
                        catch(e) {
                            dispatcher.log.warn("Unable to compute delta", e);
                            delta = 0;
                        }

                        dispatcher.log.debug("%d seconds since last heartbeat for agent %s", delta, agent.id);

                        // If we haven't received a heartbeat for twice the time, it means our agent is probably dead...
                        if(delta > interval * 2 ) {
                            dispatcher.db.hset(agent.id, "status", "DISCONNECTED");

                            if(results[1] === 'CONNECTED') {
                                dispatcher.log.warn("Watchdog Report: Agent %s is disconnected. Last heartbeat we received was %d", agent.id, results[0]);
                                dispatcher.emit('agent-disconnected', {id:agent.id, lastHeartbeatTs: results[0]});
                            }

                            // Close this watch dog, another one will be created when the agent is reconnected
                            dispatcher.log.info("Removing watchdog for agent %s", agent.id);
                            clearInterval(_this.watchDogInterval);
                        }
                        else {
                            dispatcher.log.debug("Watchdog Report: Agent %s is still connected", agent.id);
                        }
                    });


            }, interval * 2000);
        }

        return WatchDog;
    })();

    module.exports = WatchDog;
})();