All files / core MessageBusPromise.ts

78.57% Statements 33/42
37.5% Branches 3/8
83.33% Functions 5/6
78.05% Lines 32/41
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126    2x 2x   2x   4x 4x 4x 4x 4x 4x 4x   4x   4x     4x     4x                     4x 4x 4x 4x 4x     4x 4x     4x   4x 4x 4x                         4x 4x 2x 2x 2x           4x                                                                                                         2x
 
import { IMessageBus } from '../types/IMessageBus';
import { createGUID, isNullOrUndefined, ArgumentException, ArgumentNullException, TimeoutException } from '../common/common';
import { Promise } from 'es6-promise';
 
export class MessageBusPromise<TData, TResult> {
 
    private _messageBus: IMessageBus = null;
    private _timeout: number = 30000;
    private _useSync: boolean = false;
    private _data: TData = null;
    private _topic: string = '';
    private _doLog: boolean = false;
    private _logger: any = console;
 
    constructor(messageBus: IMessageBus, topic: string, data: TData, useSync?: boolean, timeout?: number) {
 
        Iif (isNullOrUndefined(messageBus)) {
            throw new ArgumentNullException('messageBus');
        }
        Iif (isNullOrUndefined(data)) {
            throw new ArgumentNullException('data');
        }
        Iif (isNullOrUndefined(topic)) {
            throw new ArgumentNullException('topic');
        }
        /* istanbul ignore next */
        if (isNullOrUndefined(timeout) || timeout < 0) {
            timeout = 30000;
        }
        /* istanbul ignore next */
        if (isNullOrUndefined(useSync)) {
            useSync = false;
        }
        this._useSync = useSync;
        this._timeout = timeout;
        this._messageBus = messageBus;
        this._data = data;
        this._topic = topic;
    };
 
    public send = () => {
        return new Promise(this.executor);
    }
 
    private executor = (resolve: (data: TResult) => void, reject: (data: any) => void) => {
 
        const guid = createGUID();
        const receiverTopicSuccess = this._topic + '__' + guid;
        let timeoutFunc = null;
 
        const receiver = {
            receive: (data: TResult) => {
                this._messageBus.unsubscribe(receiverTopicSuccess, receiver);
                if (!isNullOrUndefined(timeoutFunc)) {
                    clearTimeout(timeoutFunc);
                }
                this.log('Received data: ');
                this.log(data);
                resolve(data);
            }
        }
        this._messageBus.subscribe(receiverTopicSuccess, receiver);
        timeoutFunc = this.runAsync(() => {
            this.error('Timeout (' + this._timeout + '): ' + this._topic);
            this._messageBus.unsubscribe(receiverTopicSuccess, receiver);
            reject(new TimeoutException(this._timeout, this._topic));
        });
 
        const data = Object.assign({}, this._data, {
            __sender: receiverTopicSuccess
        });
        this._messageBus.publish(this._topic, data);
    };
 
    /* istanbul ignore next */
    private log(message: string | any) {
        if (this._doLog !== true) {
            return;
        }
        if (isNullOrUndefined(this._logger)) {
            throw new ArgumentException('logger');
        }
        if (!isNullOrUndefined(this._logger.log)) {
            this._logger.log(message);
        }
    }
 
    /* istanbul ignore next */
    private warn(message: string) {
        if (this._doLog !== true) {
            return;
        }
        if (isNullOrUndefined(this._logger)) {
            throw new ArgumentException('logger');
        }
        if (!isNullOrUndefined(this._logger.warn)) {
            this._logger.warn(message);
        }
    }
 
    /* istanbul ignore next */
    private error(message: string) {
        if (this._doLog !== true) {
            return;
        }
        if (isNullOrUndefined(this._logger)) {
            throw new ArgumentException('logger');
        }
        if (!isNullOrUndefined(this._logger.error)) {
            this._logger.error(message);
        }
    }
 
    /* istanbul ignore next */
    private runAsync = (func: () => void) => {
        if (this._useSync === false) {
            return setTimeout(() => {
                func();
            }, this._timeout);
        } else {
            this.warn('Running in sync. Do not do this in production!');
            func();
        }
    };
}