Skip to content
Snippets Groups Projects
Dirty.js 10.15 KiB
/**
 * Created by raos on 6/28/17.
 */

/* @depend QfqEvents.js */

/**
 * Qfq Namespace
 *
 * @namespace QfqNS
 */
var QfqNS = QfqNS || {};

(function (n) {
    'use strict';

    n.Dirty = function (dirtyUrl) {
        this.dirtyUrl = dirtyUrl;

        this.eventEmitter = new EventEmitter();
        this.successTimerId = null;
        this.deniedTimerId = null;
        this.lockTimeoutInMilliseconds = n.Dirty.NO_LOCK_TIMEOUT;
    };

    n.Dirty.NO_LOCK_TIMEOUT = -1;

    n.Dirty.EVENTS = {
        STARTED: 'dirty.notify.started',
        SUCCESS: 'dirty.notify.success',
        ENDED: 'dirty.notify.ended',
        FAILED: 'dirty.notify.failed',
        DENIED: 'dirty.notify.denied',
        DENIED_TIMEOUT: 'dirty.timeout.denied',
        SUCCESS_TIMEOUT: 'dirty.timeout.success',

        RELEASE_STARTED: 'dirty.release.started',
        RELEASE_ENDED: 'dirty.release.ended',
        RELEASE_SUCCESS: 'dirty.release.success',
        RELEASE_FAILED: 'dirty.release.failed',

        RENEWAL_STARTED: 'dirty.renewal.started',
        RENEWAL_ENDED: 'dirty.renewal.ended',
        RENEWAL_SUCCESS: 'dirty.renewal.success',
        RENEWAL_DENIED: 'dirty.renewal.denied',
        RENEWAL_FAILED: 'dirty.renewal.failed'
    };

    n.Dirty.ENDPOINT_OPERATIONS = {
        /** Aquire Lock */
        LOCK: "lock",
        /** Release Lock */
        RELEASE: "release",
        /** Renew Lock */
        RENEW: "extend"
    };

    n.Dirty.MINIMUM_TIMER_DELAY_IN_SECONDS = 5;
    n.Dirty.MILLISECONDS_PER_SECOND = 1000;

    n.Dirty.prototype.on = n.EventEmitter.onMixin;

    /**
     * Notify the server that SIP is becoming dirty.
     *
     * @param sip {string} sip.
     * @public
     */
    n.Dirty.prototype.notify = function (sip, optionalQueryParameters) {
        var eventData;

        if (!this.dirtyUrl) {
            n.Log.debug("notify: cannot contact server, no dirtyUrl.");
            return;
        }
        eventData = n.EventEmitter.makePayload(this, null);
        this.eventEmitter.emitEvent(n.Dirty.EVENTS.STARTED, eventData);
        $.ajax({
            url: this.makeUrl(sip, n.Dirty.ENDPOINT_OPERATIONS.LOCK, optionalQueryParameters),
            type: 'GET',
            cache: false
        })
            .done(this.ajaxNotifySuccessHandler.bind(this))
            .fail(this.ajaxNotifyErrorHandler.bind(this));
    };

    /**
     * @private
     * @param data
     * @param textStatus
     * @param jqXHR
     */
    n.Dirty.prototype.ajaxNotifySuccessHandler = function (data, textStatus, jqXHR) {
        var eventData = n.EventEmitter.makePayload(this, data);
        if (data.status && data.status === "success") {
            this.eventEmitter.emitEvent(n.Dirty.EVENTS.SUCCESS, eventData);
        } else {
            this.eventEmitter.emitEvent(n.Dirty.EVENTS.DENIED, eventData);
        }

        this.setTimeoutIfRequired(data, eventData);
        this.eventEmitter.emitEvent(n.Dirty.EVENTS.ENDED, eventData);
    };

    /**
     * Set timers based on server response. Timers are only set when `ajaxData` contains a `lock_timeout` attribute.
     * `lock_timeout` is expected to hold the timeout in seconds.
     *
     * @param ajaxData data received from server
     * @param eventData data passed when event is emitted.
     * @private
     */
    n.Dirty.prototype.setTimeoutIfRequired = function (ajaxData, eventData) {
        var timeoutInMilliseconds;

        if (!ajaxData.lock_timeout || ajaxData.lock_timeout < n.Dirty.MINIMUM_TIMER_DELAY_IN_SECONDS) {
            this.lockTimeoutInMilliseconds = n.Dirty.NO_LOCK_TIMEOUT;
            return;
        }

        this.lockTimeoutInMilliseconds = ajaxData.lock_timeout * n.Dirty.MILLISECONDS_PER_SECOND;

        if (ajaxData.status &&
            ajaxData.status === "success") {
            this.clearSuccessTimeoutTimerIfSet();

            this.successTimerId = setTimeout((function (that, data) {
                return function () {
                    that.eventEmitter.emitEvent(n.Dirty.EVENTS.SUCCESS_TIMEOUT, data);
                };
            })(this, eventData), this.lockTimeoutInMilliseconds);
        } else {
            this.clearDeniedTimeoutTimerIfSet();

            this.deniedTimerId = setTimeout((function (that, data) {
                return function () {
                    that.eventEmitter.emitEvent(n.Dirty.EVENTS.DENIED_TIMEOUT, data);
                };
            })(this, eventData), this.lockTimeoutInMilliseconds);
        }
    };

    /**
     * @public
     */
    n.Dirty.prototype.clearSuccessTimeoutTimerIfSet = function () {
        if (this.successTimerId) {
            clearTimeout(this.successTimerId);
            this.successTimerId = null;
        }
    };

    /**
     * @private
     */
    n.Dirty.prototype.clearDeniedTimeoutTimerIfSet = function () {
        if (this.deniedTimerId) {
            clearTimeout(this.deniedTimerId);
            this.deniedTimerId = null;
        }
    };


    /**
     * @private
     * @param jqXHR
     * @param textStatus
     * @param errorThrown
     */
    n.Dirty.prototype.ajaxNotifyErrorHandler = function (jqXHR, textStatus, errorThrown) {
        var eventData = n.EventEmitter.makePayload(this, null, {
            textStatus: textStatus,
            errorThrown: errorThrown,
            jqXHR: jqXHR
        });

        this.lockTimeoutInMilliseconds = n.Dirty.NO_LOCK_TIMEOUT;

        this.eventEmitter.emitEvent(n.Dirty.EVENTS.FAILED, eventData);
        this.eventEmitter.emitEvent(n.Dirty.EVENTS.ENDED, eventData);
    };

    /**
     * Release lock.
     *
     * @param sip {string} sip
     * @public
     */
    n.Dirty.prototype.release = function (sip, optionalQueryParameters, async) {
        var eventData;
        if (async === undefined) {
            async = true;
        }

        if (!this.dirtyUrl) {
            n.Log.debug("release: cannot contact server, no dirtyUrl.");
            return;
        }
        eventData = n.EventEmitter.makePayload(this, null);
        this.eventEmitter.emitEvent(n.Dirty.EVENTS.RELEASE_STARTED, eventData);
        $.ajax({
            url: this.makeUrl(sip, n.Dirty.ENDPOINT_OPERATIONS.RELEASE, optionalQueryParameters),
            type: 'GET',
            cache: false,
            async: async
        })
            .done(this.ajaxReleaseSuccessHandler.bind(this))
            .fail(this.ajaxReleaseErrorHandler.bind(this));
    };
    /**
     * @private
     * @param data
     * @param textStatus
     * @param jqXHR
     */
    n.Dirty.prototype.ajaxReleaseSuccessHandler = function (data, textStatus, jqXHR) {
        n.Log.debug("Dirty Release: Response received.");
        var eventData = n.EventEmitter.makePayload(this, data);
        if (data.status && data.status === "success") {
            this.eventEmitter.emitEvent(n.Dirty.EVENTS.RELEASE_SUCCESS, eventData);
        } else {
            this.eventEmitter.emitEvent(n.Dirty.EVENTS.RELEASE_FAILED, eventData);
        }

        this.lockTimeoutInMilliseconds = n.Dirty.NO_LOCK_TIMEOUT;

        this.eventEmitter.emitEvent(n.Dirty.EVENTS.RELEASE_ENDED, eventData);
    };

    /**
     * @private
     * @param jqXHR
     * @param textStatus
     * @param errorThrown
     */
    n.Dirty.prototype.ajaxReleaseErrorHandler = function (jqXHR, textStatus, errorThrown) {
        var eventData = n.EventEmitter.makePayload(this, null, {
            textStatus: textStatus,
            errorThrown: errorThrown,
            jqXHR: jqXHR
        });

        this.lockTimeoutInMilliseconds = n.Dirty.NO_LOCK_TIMEOUT;

        this.eventEmitter.emitEvent(n.Dirty.EVENTS.RELEASE_FAILED, eventData);
        this.eventEmitter.emitEvent(n.Dirty.EVENTS.RELEASE_ENDED, eventData);
    };

    /**
     * Request renewal of lock.
     *
     * @param sip {string} sip.
     * @public
     */
    n.Dirty.prototype.renew = function (sip, optionalQueryParameters) {
        var eventData;

        if (!this.dirtyUrl) {
            n.Log.debug("renew: cannot contact server, no dirtyUrl.");
            return;
        }
        eventData = n.EventEmitter.makePayload(this, null);
        this.eventEmitter.emitEvent(n.Dirty.EVENTS.RENEWAL_STARTED, eventData);
        $.ajax({
            url: this.makeUrl(sip, n.Dirty.ENDPOINT_OPERATIONS.RENEW, optionalQueryParameters),
            type: 'GET',
            cache: false
        })
            .done(this.ajaxRenewalSuccessHandler.bind(this))
            .fail(this.ajaxRenewalErrorHandler.bind(this));
    };

    /**
     * @private
     * @param data
     * @param textStatus
     * @param jqXHR
     */
    n.Dirty.prototype.ajaxRenewalSuccessHandler = function (data, textStatus, jqXHR) {
        var eventData = n.EventEmitter.makePayload(this, data);
        if (data.status && data.status === "success") {
            this.eventEmitter.emitEvent(n.Dirty.EVENTS.RENEWAL_SUCCESS, eventData);
        } else {
            this.eventEmitter.emitEvent(n.Dirty.EVENTS.RENEWAL_DENIED, eventData);
        }
        this.eventEmitter.emitEvent(n.Dirty.EVENTS.RENEWAL_ENDED, eventData);

        this.setTimeoutIfRequired(data, eventData);
    };

    /**
     * @private
     * @param jqXHR
     * @param textStatus
     * @param errorThrown
     */
    n.Dirty.prototype.ajaxRenewalErrorHandler = function (jqXHR, textStatus, errorThrown) {
        var eventData = n.EventEmitter.makePayload(this, null, {
            textStatus: textStatus,
            errorThrown: errorThrown,
            jqXHR: jqXHR
        });

        this.lockTimeoutInMilliseconds = n.Dirty.NO_LOCK_TIMEOUT;

        this.eventEmitter.emitEvent(n.Dirty.EVENTS.RENEWAL_FAILED, eventData);
        this.eventEmitter.emitEvent(n.Dirty.EVENTS.RENEWAL_ENDED, eventData);
    };

    /**
     * Create URL to endpoint.
     *
     * @param sip {string} sip of the request
     * @param operation {string} operation
     * @returns {string} complete url
     * @private
     */
    n.Dirty.prototype.makeUrl = function (sip, operation, optionalQueryParameters) {
        var queryString, mergedQueryParameterObject;

        mergedQueryParameterObject = $.extend(
            optionalQueryParameters,
            {
                s: sip,
                action: operation
            }
        );

        queryString = $.param(mergedQueryParameterObject);
        return this.dirtyUrl + "?" + queryString;
    };
})(QfqNS);