@splitsoftware/splitio-commons
Version:
Split JavaScript SDK common components
81 lines (80 loc) • 4.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.mySegmentsUpdaterFactory = void 0;
var timeout_1 = require("../../../utils/promise/timeout");
var constants_1 = require("../../../readiness/constants");
var constants_2 = require("../../../logger/constants");
var constants_3 = require("../../streaming/constants");
/**
* factory of MySegments updater, a task that:
* - fetches mySegments using `mySegmentsFetcher`
* - updates `mySegmentsCache`
* - uses `segmentsEventEmitter` to emit events related to segments data updates
*/
function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmentsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, matchingKey) {
var splits = storage.splits, rbSegments = storage.rbSegments, segments = storage.segments, largeSegments = storage.largeSegments;
var readyOnAlreadyExistentState = true;
var startingUp = true;
/** timeout and telemetry decorator for `splitChangesFetcher` promise */
function _promiseDecorator(promise) {
if (startingUp)
promise = (0, timeout_1.timeout)(requestTimeoutBeforeReady, promise);
return promise;
}
// @TODO if allowing pluggable storages, handle async execution
function updateSegments(segmentsData) {
var shouldNotifyUpdate;
if (segmentsData.type !== undefined) {
shouldNotifyUpdate = segmentsData.type === constants_3.MEMBERSHIPS_LS_UPDATE ?
largeSegments.resetSegments(segmentsData) :
segments.resetSegments(segmentsData);
}
else {
shouldNotifyUpdate = segments.resetSegments(segmentsData.ms || {});
shouldNotifyUpdate = largeSegments.resetSegments(segmentsData.ls || {}) || shouldNotifyUpdate;
}
// Notify update if required
if ((splits.usesSegments() || rbSegments.usesSegments()) && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
readyOnAlreadyExistentState = false;
segmentsEventEmitter.emit(constants_1.SDK_SEGMENTS_ARRIVED);
}
}
function _mySegmentsUpdater(retry, segmentsData, noCache, till) {
var updaterPromise = segmentsData ?
// If segmentsData is provided, there is no need to fetch mySegments
new Promise(function (res) { updateSegments(segmentsData); res(true); }) :
// If not provided, fetch mySegments
mySegmentsFetcher(matchingKey, noCache, till, _promiseDecorator).then(function (segments) {
// Only when we have downloaded segments completely, we should not keep retrying anymore
startingUp = false;
updateSegments(segments);
return true;
});
return updaterPromise.catch(function (error) {
if (startingUp && retriesOnFailureBeforeReady > retry) {
retry += 1;
log.warn(constants_2.SYNC_MYSEGMENTS_FETCH_RETRY, [retry, error]);
return _mySegmentsUpdater(retry); // no need to forward `segmentList` and `noCache` params
}
else {
startingUp = false;
}
return false;
});
}
/**
* MySegments updater returns a promise that resolves with a `false` boolean value if it fails to fetch mySegments or synchronize them with the storage.
* Returned promise will not be rejected.
*
* @param segmentsData - it can be:
* (1) the list of mySegments names to sync in the storage,
* (2) an object with a segment name and action (true: add, or false: delete) to update the storage,
* (3) or `undefined`, for which the updater will fetch mySegments in order to sync the storage.
* @param noCache - true to revalidate data to fetch
* @param till - query param to bypass CDN requests
*/
return function mySegmentsUpdater(segmentsData, noCache, till) {
return _mySegmentsUpdater(0, segmentsData, noCache, till);
};
}
exports.mySegmentsUpdaterFactory = mySegmentsUpdaterFactory;