UNPKG

@glue42/bbg-market-data

Version:

A high-level API that wraps existing Glue42 Bloomberg Bridge Market Data interop methods. The API is based on the jBloomberg open source wrapper.

226 lines 12.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MdfBridge = void 0; const tslib_1 = require("tslib"); const callback_registry_1 = tslib_1.__importDefault(require("callback-registry")); const promise_wrapper_1 = require("../promise-wrapper"); const utils_1 = require("./../utils"); const ON_EVENT = "bbg-event"; /** * MDF API facade. */ class MdfBridge { constructor(interop, apiId, apiVersion, protocolMethods, logger) { this.interop = interop; this.apiId = apiId; this.apiVersion = apiVersion; this.protocolMethods = protocolMethods; this.logger = logger; this.registry = callback_registry_1.default(); this.registerEventsCallbackPW = new promise_wrapper_1.PromiseWrapper(); /** * Enable multiple library instances. */ this.eventsCallbackMethodName = `OnBBGRequestData_${this.apiVersion}_${this.apiId}`; this.registerEventsCallbackMethod(); } get eventsCallbackMethod() { return this.eventsCallbackMethodName; } /** * Returns a promise which either resolves when the callback method was registered successfully or rejects when registration failed. */ ready() { return tslib_1.__awaiter(this, void 0, void 0, function* () { yield this.registerEventsCallbackPW.promise; }); } /** * Subscribe to receive events for a particular request. */ onEvent(requestId, handler) { if (typeof requestId != "string") { throw new Error("requestId must be a string."); } if (typeof handler != "function") { throw new Error("handler must be function."); } const _handler = ({ requestCorrelationId, msg }) => { if (requestCorrelationId === requestId) { handler(msg); } }; return this.registry.add(ON_EVENT, _handler); } /** * Invokes the MDF API to create a non-subscription request. */ createRequest(args) { return tslib_1.__awaiter(this, void 0, void 0, function* () { yield this.invokeCreateRequest(this.protocolMethods.CreateRequest, args, `MDF API failed to create the non-subscription request with id "${args.requestCorrelationId}".`); }); } /** * Invokes the MDF API to create a subscription request. */ createSubscriptionRequest(args) { return tslib_1.__awaiter(this, void 0, void 0, function* () { yield this.invokeCreateRequest(this.protocolMethods.CreateSubscriptionRequest, args, `MDF API failed to create the subscription request with id "${args.requestCorrelationId}".`); }); } /** * Invokes the MDF API to cancel a request. */ closeRequest(requestId, reason) { var _a, _b, _c, _d; return tslib_1.__awaiter(this, void 0, void 0, function* () { const invocationArgs = { requestCorrelationIds: [requestId], reason, }; const methodDef = this.protocolMethods.CancelRequests; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`Attempting to invoke interop method "${methodDef.name}" with args ${JSON.stringify(invocationArgs)}`); const defaultErrorMessage = `MDF API failed to close request with id "${requestId}".`; try { const { returned } = yield this.interop.invoke(methodDef, invocationArgs); (_b = this.logger) === null || _b === void 0 ? void 0 : _b.info(`Successfully invoked interop method "${methodDef.name}" - ${JSON.stringify(returned)}`); const terminalResults = (_c = returned.Result) !== null && _c !== void 0 ? _c : returned.result; const thisRequestResult = (Array.isArray(terminalResults) ? terminalResults : []).find(({ correlationId }) => correlationId === requestId); if (thisRequestResult == null || thisRequestResult.success !== true) { const errorMessage = typeof (thisRequestResult === null || thisRequestResult === void 0 ? void 0 : thisRequestResult.message) === "string" ? thisRequestResult.message : defaultErrorMessage; return Promise.reject(new Error(errorMessage)); } } catch (error) { const errorMessage = utils_1.extractErrorMessage(error, defaultErrorMessage); (_d = this.logger) === null || _d === void 0 ? void 0 : _d.warn(`Failed to invoke interop method "${methodDef.name}" - ${errorMessage}`); return Promise.reject(new Error(errorMessage)); } }); } /** * Invokes the MDF API to close a session. */ closeSession(sessionName) { var _a, _b, _c, _d; return tslib_1.__awaiter(this, void 0, void 0, function* () { const invocationArgs = { sessionName, }; const methodDef = this.protocolMethods.CloseSession; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`Attempting to invoke interop method "${methodDef.name}" with args ${JSON.stringify(invocationArgs)}`); try { const { returned } = yield this.interop.invoke(methodDef, invocationArgs); (_b = this.logger) === null || _b === void 0 ? void 0 : _b.info(`Successfully invoked interop method ${methodDef.name} - ${JSON.stringify(returned)}`); const terminalResult = (_c = returned.Result) !== null && _c !== void 0 ? _c : returned.result; if (terminalResult == null || terminalResult.success === false) { const errorMessage = typeof (terminalResult === null || terminalResult === void 0 ? void 0 : terminalResult.message) === "string" ? terminalResult.message : `MDF API failed to close session "${sessionName}".`; return Promise.reject(new Error(errorMessage)); } } catch (error) { const errorMessage = utils_1.extractErrorMessage(error); (_d = this.logger) === null || _d === void 0 ? void 0 : _d.warn(`Failed to invoke interop method "${methodDef.name}" - ${errorMessage}`); return Promise.reject(new Error(errorMessage)); } }); } /** * Subscribes to MDF API Interop stream that streams Bloomberg Heartbeat. */ subscribeForConnectionStatus(retryPeriodMsecs, subscriber) { var _a, _b, _c; return tslib_1.__awaiter(this, void 0, void 0, function* () { // TODO: Implement resubscription logic. const methodDef = this.protocolMethods.SubscribeStatus; try { (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`Attempting to subscribe to "${methodDef.name}".`); const subscription = yield this.interop.subscribe(methodDef, { arguments: { settings: { retryPeriodMsecs } }, }); const handleData = ({ SubscriptionStatus }) => subscriber.onData(SubscriptionStatus); const handleError = () => subscriber.onError(); const handleClose = () => subscriber.onClose(); subscription.onData(({ data }) => { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.trace(`Stream "${methodDef.name}" subscription data - ${JSON.stringify(data)}`); handleData(data); }); subscription.onFailed((error) => { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.warn(`Stream "${methodDef.name}" subscription failed - ${JSON.stringify(error)}`); handleError(); }); subscription.onClosed((info) => { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`Stream "${methodDef.name}" subscription closed - ${JSON.stringify(info)}`); handleClose(); }); (_b = this.logger) === null || _b === void 0 ? void 0 : _b.info(`Successfully subscribed to "${methodDef.name}".`); } catch (error) { const errorMsg = utils_1.extractErrorMessage(error); (_c = this.logger) === null || _c === void 0 ? void 0 : _c.error(`Failed to subscribe to "${methodDef.name}" - ${errorMsg}`); subscriber.onError(); } }); } registerEventsCallbackMethod() { var _a, _b, _c; return tslib_1.__awaiter(this, void 0, void 0, function* () { const invocationHandler = (data) => { this.registry.execute(ON_EVENT, data); }; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`Attempting to register events callback "${this.eventsCallbackMethodName}".`); try { yield this.interop.register(this.eventsCallbackMethodName, invocationHandler); this.registerEventsCallbackPW.resolve(); (_b = this.logger) === null || _b === void 0 ? void 0 : _b.info(`Successfully registered events callback "${this.eventsCallbackMethodName}".`); } catch (error) { const errorMessage = utils_1.extractErrorMessage(error); const kindMessage = `Failed to register events callback "${this.eventsCallbackMethodName}" - ${errorMessage}`; (_c = this.logger) === null || _c === void 0 ? void 0 : _c.error(kindMessage); this.registerEventsCallbackPW.reject(new Error(kindMessage)); } }); } invokeCreateRequest(methodDef, args, defaultErrorMessage) { var _a, _b, _c, _d; return tslib_1.__awaiter(this, void 0, void 0, function* () { yield this.ready(); const invocationArgs = Object.assign(Object.assign({}, args), { callbackMethod: this.eventsCallbackMethodName }); const invokeOptions = { methodResponseTimeoutMs: 180 * 1000, }; const argsToLog = { settings: args.settings, requestCorrelationId: args.requestCorrelationId, operation: args.operation, operationArgs: args.operationArgs, subscriptions: args.subscriptions, }; delete argsToLog.settings.sessionIdentityOptions; delete argsToLog.settings.sessionOptions; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`Attempting to invoke interop method "${methodDef.name}" with args ${JSON.stringify(argsToLog)}`); try { const { returned } = yield this.interop.invoke(methodDef, invocationArgs, "best", invokeOptions); (_b = this.logger) === null || _b === void 0 ? void 0 : _b.info(`Successfully invoked interop method "${methodDef.name}" - ${JSON.stringify(returned)}`); const terminalResult = (_c = returned.Result) !== null && _c !== void 0 ? _c : returned.result; if (terminalResult == null || terminalResult.success === false) { const errorMessage = typeof (terminalResult === null || terminalResult === void 0 ? void 0 : terminalResult.message) === "string" ? terminalResult.message : defaultErrorMessage; return Promise.reject(new Error(errorMessage)); } } catch (error) { const errorMessage = utils_1.extractErrorMessage(error, defaultErrorMessage); (_d = this.logger) === null || _d === void 0 ? void 0 : _d.warn(`Failed to invoke interop method "${methodDef.name}" - ${errorMessage}`); return Promise.reject(new Error(errorMessage)); } }); } } exports.MdfBridge = MdfBridge; //# sourceMappingURL=mdf-bridge.js.map