@splitsoftware/splitio-commons
Version:
Split JavaScript SDK common components
79 lines (78 loc) • 4.33 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.splitChangesFetcherFactory = void 0;
var constants_1 = require("../../../utils/constants");
var settingsValidation_1 = require("../../../utils/settingsValidation");
var constants_2 = require("../../../logger/constants");
var key_1 = require("../../../utils/key");
var PROXY_CHECK_INTERVAL_MILLIS_CS = 60 * 60 * 1000; // 1 hour in Client Side
var PROXY_CHECK_INTERVAL_MILLIS_SS = 24 * PROXY_CHECK_INTERVAL_MILLIS_CS; // 24 hours in Server Side
function sdkEndpointOverridden(settings) {
return settings.urls.sdk !== settingsValidation_1.base.urls.sdk;
}
function isSplitChangesLegacyResponse(data) {
return data.splits != null;
}
function partitionByStatus(items, till, since) {
var updated = [], removed = [];
items.forEach(function (item) { return item.status === 'ARCHIVED' ? removed.push(item.name) : updated.push(item); });
return { updated: updated, removed: removed, till: till, since: since };
}
/**
* Factory of SplitChanges fetcher.
* SplitChanges fetcher is a wrapper around `splitChanges` API service that parses the response and handle errors.
*/
// @TODO breaking: drop support for Split Proxy below v5.10.0 and simplify the implementation
function splitChangesFetcherFactory(params) {
var fetchSplitChanges = params.serviceApi.fetchSplitChanges, settings = params.settings, storage = params.storage;
var log = settings.log;
var PROXY_CHECK_INTERVAL_MILLIS = (0, key_1.checkIfServerSide)(settings) ? PROXY_CHECK_INTERVAL_MILLIS_SS : PROXY_CHECK_INTERVAL_MILLIS_CS;
var lastProxyCheckTimestamp;
function splitChangesFetcher(since, noCache, till, rbSince,
// Optional decorator for `fetchSplitChanges` promise, such as timeout or time tracker
decorator) {
// Recheck proxy
if (lastProxyCheckTimestamp && (Date.now() - lastProxyCheckTimestamp) > PROXY_CHECK_INTERVAL_MILLIS) {
settings.sync.flagSpecVersion = constants_1.FLAG_SPEC_VERSION;
}
var splitsPromise = fetchSplitChanges(since, noCache, till, settings.sync.flagSpecVersion === constants_1.FLAG_SPEC_VERSION ? rbSince : undefined)
.catch(function (err) {
// Handle proxy error with spec 1.3
if ((!err.statusCode || err.statusCode === 400) && sdkEndpointOverridden(settings) && settings.sync.flagSpecVersion === constants_1.FLAG_SPEC_VERSION) {
log.error(constants_2.LOG_PREFIX_SYNC + 'Proxy error detected. Retrying with spec 1.2. If you are using Split Proxy, please upgrade to latest version');
lastProxyCheckTimestamp = Date.now();
settings.sync.flagSpecVersion = '1.2'; // fallback to 1.2 spec
return fetchSplitChanges(since, noCache, till); // retry request without rbSince
}
throw err;
});
if (decorator)
splitsPromise = decorator(splitsPromise);
return splitsPromise
.then(function (resp) { return resp.json(); })
.then(function (data) {
// Using flag spec version 1.2 or below
if (isSplitChangesLegacyResponse(data)) {
return { d: partitionByStatus(data.splits || [], data.till, data.since) };
}
// Proxy recovery
if (lastProxyCheckTimestamp) {
log.info(constants_2.LOG_PREFIX_SYNC + 'Proxy error recovered');
lastProxyCheckTimestamp = undefined;
return splitChangesFetcher(-1, undefined, undefined, -1)
.then(function (splitChangesResponse) {
return Promise.all([storage.definitions.clear(), storage.rbSegments.clear()])
.then(function () { return splitChangesResponse; });
});
}
var ff = data.ff, rbs = data.rbs;
return {
d: (ff === null || ff === void 0 ? void 0 : ff.d) ? partitionByStatus(ff.d, ff.t, ff.s) : undefined,
rbs: (rbs === null || rbs === void 0 ? void 0 : rbs.d) ? partitionByStatus(rbs.d, rbs.t, rbs.s) : undefined,
};
});
}
splitChangesFetcher.type = 'feature flags';
return splitChangesFetcher;
}
exports.splitChangesFetcherFactory = splitChangesFetcherFactory;