APIs

Show:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const _ = require("underscore");
const events_1 = require("events");
const node_opcua_assert_1 = require("node-opcua-assert");
function has_expired(watchDogData, currentTime) {
    const elapsed_time = currentTime - watchDogData.last_seen;
    return elapsed_time > watchDogData.timeout;
}
function keepAliveFunc() {
    const self = this;
    node_opcua_assert_1.assert(self._watchDog instanceof WatchDog);
    node_opcua_assert_1.assert(_.isNumber(self._watchDogData.key));
    self._watchDogData.last_seen = Date.now();
    if (self.onClientSeen) {
        self.onClientSeen(new Date(self._watchDogData.last_seen));
    }
}
class WatchDog extends events_1.EventEmitter {
    constructor() {
        super();
        this._watchdogDataMap = {};
        this._counter = 0;
        this._current_time = Date.now();
        this._visit_subscriber_b = this._visit_subscriber.bind(this);
        this._timer = null; // as NodeJS.Timer;
    }
    _visit_subscriber() {
        const self = this;
        self._current_time = Date.now();
        const expired_subscribers = _.filter(self._watchdogDataMap, function (watchDogData) {
            watchDogData.visitCount += 1;
            return has_expired(watchDogData, self._current_time);
        });
        //xx console.log("_visit_subscriber", _.map(expired_subscribers, _.property("key")));
        if (expired_subscribers.length) {
            self.emit("timeout", expired_subscribers);
        }
        expired_subscribers.forEach((watchDogData) => {
            self.removeSubscriber(watchDogData.subscriber);
            watchDogData.subscriber.watchdogReset();
        });
        //xx self._current_time = Date.now();
    }
    /**
     * add a subscriber to the WatchDog.
     * @method addSubscriber
     *
     * add a subscriber to the WatchDog.
     *
     * This method modifies the subscriber be adding a
     * new method to it called 'keepAlive'
     * The subscriber must also provide a "watchdogReset". watchdogReset will be called
     * if the subscriber failed to call keepAlive withing the timeout period.
     * @param subscriber
     * @param timeout
     * @return {number}
     */
    addSubscriber(subscriber, timeout) {
        const self = this;
        self._current_time = Date.now();
        timeout = timeout || 1000;
        node_opcua_assert_1.assert(_.isNumber(timeout), " invalid timeout ");
        node_opcua_assert_1.assert(_.isFunction(subscriber.watchdogReset), " the subscriber must provide a watchdogReset method ");
        node_opcua_assert_1.assert(!_.isFunction(subscriber.keepAlive));
        self._counter += 1;
        const key = self._counter;
        subscriber._watchDog = self;
        subscriber._watchDogData = {
            key: key,
            subscriber: subscriber,
            timeout: timeout,
            last_seen: self._current_time,
            visitCount: 0
        };
        self._watchdogDataMap[key] = subscriber._watchDogData;
        if (subscriber.onClientSeen) {
            subscriber.onClientSeen(new Date(subscriber._watchDogData.last_seen));
        }
        subscriber.keepAlive = keepAliveFunc.bind(subscriber);
        // start timer when the first subscriber comes in
        if (self.subscriberCount === 1) {
            node_opcua_assert_1.assert(self._timer === null);
            this._start_timer();
        }
        return key;
    }
    removeSubscriber(subscriber) {
        if (!subscriber._watchDog) {
            return; // already removed !!!
        }
        node_opcua_assert_1.assert(subscriber._watchDog instanceof WatchDog);
        node_opcua_assert_1.assert(_.isNumber(subscriber._watchDogData.key));
        node_opcua_assert_1.assert(_.isFunction(subscriber.keepAlive));
        node_opcua_assert_1.assert(this._watchdogDataMap.hasOwnProperty(subscriber._watchDogData.key));
        delete this._watchdogDataMap[subscriber._watchDogData.key];
        delete subscriber._watchDog;
        delete subscriber._watchDogData;
        delete subscriber.keepAlive;
        // delete timer when the last subscriber comes out
        //xx console.log("xxxx WatchDog.prototype.removeSubscriber ",this.subscriberCount );
        if (this.subscriberCount === 0) {
            this._stop_timer();
        }
    }
    shutdown() {
        node_opcua_assert_1.assert(this._timer === null && Object.keys(this._watchdogDataMap).length === 0, " leaking subscriber in watchdog");
    }
    /**
     * returns the number of subscribers using the WatchDog object.
     * @property subscriberCount
     * @type {number}
     */
    get subscriberCount() {
        return Object.keys(this._watchdogDataMap).length;
    }
    _start_timer() {
        node_opcua_assert_1.assert(this._timer === null, " setInterval already called ?");
        this._timer = setInterval(this._visit_subscriber_b, 1000);
    }
    _stop_timer() {
        node_opcua_assert_1.assert(this._timer !== null, "_stop_timer already called ?");
        if (this._timer !== null) {
            clearInterval(this._timer);
            this._timer = null;
        }
    }
}
exports.WatchDog = WatchDog;
//# sourceMappingURL=watchdog.js.map