diffusion
Version:
Diffusion JavaScript client
237 lines (236 loc) • 9.34 kB
JavaScript
;
/**
* @module Routing
*/
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TopicCache = void 0;
var topic_cache_datatype_entry_1 = require("./../routing/topic-cache-datatype-entry");
var topic_cache_no_value_entry_1 = require("./../routing/topic-cache-no-value-entry");
var topic_cache_time_series_entry_1 = require("./../routing/topic-cache-time-series-entry");
var errors_1 = require("../../errors/errors");
var topic_type_1 = require("../../topics/topic-type");
var topics_1 = require("../../topics/topics");
/**
* The topic cache used by the internal session to cache all topic values that
* the session subscribes to.
*/
var TopicCache = /** @class */ (function () {
/**
* Create a new TopicCache instance
*
* @param datatypes the data types
*/
function TopicCache(datatypes) {
/**
* All the topic cache entries by their topic path
*/
this.byPath = {};
/**
* All the topic cache entries by their ID
*/
this.byId = {};
this.datatypes = datatypes;
}
/**
* Handle a subscription to a new topic
*
* This is called by the internal session when the client subscribes to a
* new topic. A new entry {@link TopicCacheEntry} is created and all streams
* in the stream registry that select the subscribed path will be added to
* that entry.
*
* The entry will then be notified of the initial subscription.
*
* @param info the information about the new topic
* @param registry the stream registry
*/
TopicCache.prototype.handleSubscription = function (info, registry) {
var path = info.path;
var streams = registry.streamsFor(path, info.specification);
var entry;
switch (info.specification.type) {
case topic_type_1.TopicTypeEnum.JSON:
case topic_type_1.TopicTypeEnum.BINARY:
case topic_type_1.TopicTypeEnum.STRING:
case topic_type_1.TopicTypeEnum.DOUBLE:
case topic_type_1.TopicTypeEnum.INT64:
case topic_type_1.TopicTypeEnum.RECORD_V2:
var datatype = this.datatypes.get(info.specification.type);
if (datatype === null) {
throw new errors_1.InternalError('Invalid topic type');
}
entry = new topic_cache_datatype_entry_1.DatatypeCacheEntry(streams, path, info.specification, datatype);
break;
case topic_type_1.TopicTypeEnum.TIME_SERIES:
var eventType = this.datatypes.get(info.specification.properties.TIME_SERIES_EVENT_VALUE_TYPE);
if (eventType === null) {
throw new errors_1.InternalError('Invalid timeseries event type');
}
entry = new topic_cache_time_series_entry_1.TimeSeriesCacheEntry(streams, path, info.specification, eventType);
break;
default:
entry = new topic_cache_no_value_entry_1.NoValueEntry(streams, path, info.specification);
}
var oldByPath = this.byPath[path];
this.byPath[path] = entry;
if (oldByPath) {
throw new errors_1.InternalError("Existing cache entry for " + path);
}
var oldById = this.byId[info.id];
this.byId[info.id] = entry;
if (oldById) {
throw new errors_1.InternalError("Existing cache entry for " + info.id);
}
entry.notifyInitialSubscription(registry);
};
/**
* Clear the topic cache and notify all entries of an unsubscription
*
* @param registry the stream registry
*/
TopicCache.prototype.notifyUnsubscriptionOfAllTopics = function (registry) {
// eslint-disable-next-line guard-for-in
for (var id in this.byId) {
this.byId[id].notifyUnsubscription(topics_1.UnsubscribeReasonEnum.SUBSCRIPTION_REFRESH, registry);
}
this.byPath = {};
this.byId = {};
};
/**
* Handle a value on a given topic ID
*
* @param id the topic ID
* @param content the new content
* @param registry the stream registry
* @param handler an error handler that will be called with a {@link SessionError}
* if no cache entry could be found or an {@link InvalidDataError} if the delta
* could not be applied
*/
TopicCache.prototype.handleValue = function (id, content, registry, handler) {
var errorHandler = handler.getErrorHandler();
var entry = this.byId[id];
if (entry) {
entry.handleValue(content, registry, errorHandler);
}
else {
errorHandler(new errors_1.SessionError("Data loss on topic with ID: " + id + " - possibly due to reconnection"));
}
};
/**
* Handle a delta on a given topic ID
*
* @param id the topic ID
* @param delta the delta content
* @param registry the stream registry
* @param handler an error handler that will be called with a {@link SessionError}
* if no cache entry could be found or an {@link InvalidDataError} if the delta
* could not be applied
*/
TopicCache.prototype.handleDelta = function (id, delta, registry, handler) {
var errorHandler = handler.getErrorHandler();
var entry = this.byId[id];
if (entry) {
entry.handleDelta(delta, registry, errorHandler);
}
else {
errorHandler(new errors_1.SessionError("Data loss on topic with ID: " + id + " - possibly due to reconnection"));
}
};
/**
* Handle an unsubscription event on a given topic ID
*
* @param id the topic ID
* @param reason reason for unsubscribing
* @param registry the stream registry
*/
TopicCache.prototype.handleUnsubscription = function (id, reason, registry) {
var entry = this.byId[id];
delete this.byId[id];
if (entry) {
var path = entry.getTopicPath();
delete this.byPath[path];
entry.notifyUnsubscription(reason, registry);
}
};
/**
* Add a new stream to the cache
*
* The stream will be added to all current entries that the stream selects.
*
* @param selector the topic selector of the topics that the stream should
* receive events for
* @param stream the stream adapter to add
* @param registry the stream registry
* @throws an {@link InvalidDataError} if any value received is incompatible with the data type
* of the stream or does not represent a valid value.
*/
TopicCache.prototype.newStream = function (selector, stream, registry) {
for (var path in this.byPath) {
// eslint-disable-next-line no-prototype-builtins
if (this.byPath.hasOwnProperty(path)) {
var entry = this.byPath[path];
var specification = entry.getTopicSpecification();
if (selector.selects(path) && stream.selects(specification)) {
entry.addStream(stream.adapter ? stream.adapter(specification) : stream, registry);
}
}
}
};
/**
* Remove a stream from the cache
*
* Removes the stream from all entries that contain it.
*
* @param stream the stream adapter to remove
* @param registry the stream registry
*/
TopicCache.prototype.removeStream = function (stream, registry) {
for (var path in this.byPath) {
// eslint-disable-next-line no-prototype-builtins
if (this.byPath.hasOwnProperty(path)) {
this.byPath[path].removeStream(stream, registry);
}
}
};
/**
* Remove all streams from the cache
*
* Removes all streams from all entries without removing the entries themselves
*/
TopicCache.prototype.removeAllStreams = function () {
var e_1, _a;
try {
for (var _b = __values(Object.getOwnPropertyNames(this.byPath)), _c = _b.next(); !_c.done; _c = _b.next()) {
var path = _c.value;
this.byPath[path].removeAllStreams();
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
};
/**
* Removes all topic cache entries
*/
TopicCache.prototype.clear = function () {
this.byPath = {};
this.byId = {};
};
return TopicCache;
}());
exports.TopicCache = TopicCache;