@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.
234 lines (233 loc) • 11.4 kB
JavaScript
import { __assign, __awaiter, __generator, __rest } from "tslib";
import CallbackRegistryFactory from "callback-registry";
import { RequestStatus } from "../request-status";
import { BloombergError, } from "./types";
import { getFailureReason, getMessageDetails, isEventOfType, isMessageOfType, isPending, setSubscriptionCreatedStatus, setSubscriptionIds, toTerminalSubscription, } from "./helpers";
import { serviceOpenedFailureHandler, sessionStartUpFailureHandler, sessionTerminatedHandler, } from "./message-handlers";
import { EventTypes } from "./event-types";
import { SubscriptionStatus } from "./types/subscription";
import { MessageTypes } from "./message-types";
import { callSafe } from "./../utils";
import CorrelationId from "./../correlationId";
var DATA_EVENT = "data-event";
var ERROR_EVENT = "error-event";
var STATUS_EVENT = "status-event";
var FAIL_EVENT = "fail-event";
var BBG_EVENT = "bbg-event";
var SubscriptionRequestImpl = (function () {
function SubscriptionRequestImpl(sessionManager, config, subscriptions, subscriptionDataHandler) {
this.sessionManager = sessionManager;
this.config = config;
this.subscriptions = subscriptions;
this.subscriptionDataHandler = subscriptionDataHandler;
this.registry = CallbackRegistryFactory();
this._status = RequestStatus.Created;
this.subscriptionsByInternalIdMap = new Map();
this.sessionInstance = this.sessionManager.getSubscriptionReqSessionInstance();
}
Object.defineProperty(SubscriptionRequestImpl.prototype, "api", {
get: function () {
var requestImpl = this;
return {
get id() {
return requestImpl.requestId;
},
get settings() {
return {
operation: requestImpl.config.operation,
service: requestImpl.config.service,
};
},
get status() {
return requestImpl._status;
},
open: requestImpl.open.bind(requestImpl),
close: requestImpl.close.bind(requestImpl),
onData: function (callback) {
return requestImpl.registry.add(DATA_EVENT, callback);
},
onError: function (callback) {
return requestImpl.registry.add(ERROR_EVENT, callback);
},
onEvent: function (callback) {
return requestImpl.registry.add(BBG_EVENT, callback);
},
onStatus: function (callback) {
callSafe(callback, requestImpl._status);
return requestImpl.registry.add(STATUS_EVENT, callback);
},
onFail: function (callback) {
return requestImpl.registry.add(FAIL_EVENT, callback);
},
};
},
enumerable: false,
configurable: true
});
SubscriptionRequestImpl.prototype.open = function (options) {
var _this = this;
if (isPending(this._status)) {
throw new Error("Request can be opened/reopened if its status is Created, Failed, Closed or Completed. Either close the request or wait it to complete.");
}
var _a = options !== null && options !== void 0 ? options : {}, session = _a.session, otherSettings = __rest(_a, ["session"]);
this.sessionInstance = this.sessionManager.getSubscriptionReqSessionInstance(session);
this.reset();
this.requestId = new CorrelationId(this.config.service, this.config.operation).value;
var handleOpenSuccess = function () {
_this.requestActivated();
};
var handleOpenFail = function (error) {
_this.requestFailed(error);
};
var handleEvent = function (event) {
_this.registry.execute(BBG_EVENT, event);
};
var messageProcessor = function (msg) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.processEventMessage(msg)];
case 1:
_a.sent();
return [2];
}
});
}); };
this.requestOpened();
var terminalSubscriptions = Array.from(this.subscriptionsByInternalIdMap.values()).map(toTerminalSubscription);
this.sessionInstance.openSubscriptionRequest(this.requestId, this.config, terminalSubscriptions, otherSettings !== null && otherSettings !== void 0 ? otherSettings : {}, handleEvent, messageProcessor, handleOpenSuccess, handleOpenFail);
};
SubscriptionRequestImpl.prototype.close = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.sessionInstance.closeRequest(this.requestId, function () { return _this.requestClosed(); })];
case 1:
_a.sent();
return [2];
}
});
});
};
SubscriptionRequestImpl.prototype.processEventMessage = function (eventMessage) {
return __awaiter(this, void 0, void 0, function () {
var error;
return __generator(this, function (_a) {
error = [
sessionStartUpFailureHandler(eventMessage),
sessionTerminatedHandler(eventMessage),
serviceOpenedFailureHandler(eventMessage),
].find(function (_a) {
var match = _a.match;
return match;
});
if (error != null) {
this.requestFailed(error.data);
return [2];
}
this.processSubscriptionErrors(eventMessage);
if (isEventOfType(eventMessage, EventTypes.SubscriptionData)) {
this.processSubscriptionData(eventMessage);
}
return [2];
});
});
};
SubscriptionRequestImpl.prototype.processSubscriptionData = function (eventMessage) {
var _this = this;
try {
var subscriptionDataByInternalIdMap = this.subscriptionDataHandler(eventMessage);
var response_1 = [];
subscriptionDataByInternalIdMap.forEach(function (data, internalId) {
var subscription = _this.subscriptionsByInternalIdMap.get(internalId);
if (subscription) {
response_1.push(__assign(__assign({}, data), { subscriptionId: subscription.subscriptionId, security: subscription.security }));
}
});
this.registry.execute(DATA_EVENT, response_1);
}
catch (error) {
console.error(error);
}
};
SubscriptionRequestImpl.prototype.processSubscriptionErrors = function (eventMessage) {
var _this = this;
var subscriptionStatusHandler = function (_a, messageType) {
var correlationIds = _a.correlationIds, eventMessage = __rest(_a, ["correlationIds"]);
var errorsMap = new Map();
if (!isMessageOfType(eventMessage, messageType)) {
return errorsMap;
}
var messageDetails = getMessageDetails(eventMessage, messageType);
(correlationIds !== null && correlationIds !== void 0 ? correlationIds : []).forEach(function (id) {
errorsMap.set(id, messageDetails === null || messageDetails === void 0 ? void 0 : messageDetails.reason);
});
return errorsMap;
};
var errors = [];
var failureErrorsByInternalIdMap = subscriptionStatusHandler(eventMessage, MessageTypes.SubscriptionFailure);
failureErrorsByInternalIdMap.forEach(function (error, internalId) {
var subscription = _this.subscriptionsByInternalIdMap.get(internalId);
if (subscription) {
subscription.status = SubscriptionStatus.SubscriptionFailure;
error.subscriptionId = subscription.subscriptionId;
}
errors.push(error);
});
var terminatedErrorsMap = subscriptionStatusHandler(eventMessage, MessageTypes.SubscriptionTerminated);
terminatedErrorsMap.forEach(function (error, internalId) {
var subscription = _this.subscriptionsByInternalIdMap.get(internalId);
if (subscription) {
subscription.status = SubscriptionStatus.SubscriptionTerminated;
error.subscriptionId = subscription.subscriptionId;
}
errors.push(error);
});
if (errors.length > 0) {
this.raiseSubscriptionErrors(errors);
var hasActiveSubscriptions = Array.from(this.subscriptionsByInternalIdMap.values()).some(function (_a) {
var status = _a.status;
return status != SubscriptionStatus.SubscriptionFailure && status != SubscriptionStatus.SubscriptionTerminated;
});
if (!hasActiveSubscriptions) {
var error = new BloombergError(EventTypes.SubscriptionStatus, "SubscriptionFailure|SubscriptionTerminated", "All subscriptions are inactive. No more updates will be received for them.");
return this.requestFailed(error);
}
}
};
SubscriptionRequestImpl.prototype.raiseSubscriptionErrors = function (errors) {
this.registry.execute(FAIL_EVENT, errors);
};
SubscriptionRequestImpl.prototype.requestOpened = function () {
this._status = RequestStatus.Opened;
this.raiseStatusChanged();
};
SubscriptionRequestImpl.prototype.requestActivated = function () {
this._status = RequestStatus.Active;
this.raiseStatusChanged();
};
SubscriptionRequestImpl.prototype.requestClosed = function () {
this._status = RequestStatus.Closed;
this.raiseStatusChanged();
};
SubscriptionRequestImpl.prototype.requestFailed = function (error) {
var reason = getFailureReason(this.requestId, error);
this.sessionInstance.disposeRequest(this.requestId, reason);
this._status = RequestStatus.Failed;
this.raiseStatusChanged();
this.registry.execute(ERROR_EVENT, error);
};
SubscriptionRequestImpl.prototype.raiseStatusChanged = function () {
this.registry.execute(STATUS_EVENT, this._status);
};
SubscriptionRequestImpl.prototype.reset = function () {
var _this = this;
this.subscriptionsByInternalIdMap.clear();
this.subscriptions.forEach(function (s) {
s = setSubscriptionIds(setSubscriptionCreatedStatus(s));
_this.subscriptionsByInternalIdMap.set(s.internalId, s);
});
};
return SubscriptionRequestImpl;
}());
export { SubscriptionRequestImpl };