@splitsoftware/splitio-commons
Version:
Split JavaScript SDK common components
125 lines (124 loc) • 6.17 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.MySegmentsUpdateWorker = void 0;
var Backoff_1 = require("../../../utils/Backoff");
var constants_1 = require("../../../utils/constants");
var constants_2 = require("./constants");
var constants_3 = require("../constants");
/**
* MySegmentsUpdateWorker factory
*/
function MySegmentsUpdateWorker(log, storage, mySegmentsSyncTask, telemetryTracker) {
var _a;
var _delay;
var _delayTimeoutID;
function createUpdateWorker(mySegmentsCache) {
var maxChangeNumber = 0; // keeps the maximum changeNumber among queued events
var currentChangeNumber = -1;
var handleNewEvent = false;
var isHandlingEvent;
var cdnBypass;
var _segmentsData; // keeps the segmentsData (if included in notification payload) from the queued event with maximum changeNumber
var backoff = new Backoff_1.Backoff(__handleMySegmentsUpdateCall);
function __handleMySegmentsUpdateCall() {
isHandlingEvent = true;
if (maxChangeNumber > Math.max(currentChangeNumber, mySegmentsCache.getChangeNumber())) {
handleNewEvent = false;
var currentMaxChangeNumber_1 = maxChangeNumber;
// fetch mySegments revalidating data if cached
var syncTask = _delay ?
new Promise(function (res) {
_delayTimeoutID = setTimeout(function () {
_delay = undefined;
mySegmentsSyncTask.execute(_segmentsData, true, cdnBypass ? maxChangeNumber : undefined).then(res);
}, _delay);
}) :
mySegmentsSyncTask.execute(_segmentsData, true, cdnBypass ? maxChangeNumber : undefined);
syncTask.then(function (result) {
if (!isHandlingEvent)
return; // halt if `stop` has been called
if (result !== false) { // Unlike `Splits|SegmentsUpdateWorker`, `mySegmentsCache.getChangeNumber` can be -1, since `/memberships` change number is optional
var storageChangeNumber = mySegmentsCache.getChangeNumber();
currentChangeNumber = storageChangeNumber > -1 ?
storageChangeNumber :
Math.max(currentChangeNumber, currentMaxChangeNumber_1); // use `currentMaxChangeNumber`, in case that `maxChangeNumber` was updated during fetch.
}
if (handleNewEvent) {
__handleMySegmentsUpdateCall();
}
else {
if (_segmentsData)
telemetryTracker.trackUpdatesFromSSE(constants_1.MEMBERSHIPS);
var attempts = backoff.attempts + 1;
if (maxChangeNumber <= currentChangeNumber) {
log.debug("Refresh completed" + (cdnBypass ? ' bypassing the CDN' : '') + " in " + attempts + " attempts.");
isHandlingEvent = false;
return;
}
if (attempts < constants_2.FETCH_BACKOFF_MAX_RETRIES) {
backoff.scheduleCall();
return;
}
if (cdnBypass) {
log.debug("No changes fetched after " + attempts + " attempts with CDN bypassed.");
isHandlingEvent = false;
}
else {
backoff.reset();
cdnBypass = true;
__handleMySegmentsUpdateCall();
}
}
});
}
else {
isHandlingEvent = false;
}
}
return {
/**
* Invoked by NotificationProcessor on MY_(LARGE)_SEGMENTS_UPDATE notifications
*
* @param changeNumber - change number of the notification
* @param segmentsData - data for KeyList or SegmentRemoval instant updates
* @param delay - optional time to wait for BoundedFetchRequest or BoundedFetchRequest updates
*/
put: function (mySegmentsData, payload, delay) {
var type = mySegmentsData.type, cn = mySegmentsData.cn;
// Discard event if it is outdated or there is a pending fetch request (_delay is set), but update target change number
if (cn <= Math.max(currentChangeNumber, mySegmentsCache.getChangeNumber()) || cn <= maxChangeNumber)
return;
maxChangeNumber = cn;
if (_delay)
return;
handleNewEvent = true;
cdnBypass = false;
_segmentsData = payload && { type: type, cn: cn, added: payload.added, removed: payload.removed };
_delay = delay;
if (backoff.timeoutID || !isHandlingEvent)
__handleMySegmentsUpdateCall();
backoff.reset();
},
stop: function () {
clearTimeout(_delayTimeoutID);
_delay = undefined;
isHandlingEvent = false;
backoff.reset();
}
};
}
var updateWorkers = (_a = {},
_a[constants_3.MEMBERSHIPS_MS_UPDATE] = createUpdateWorker(storage.segments),
_a[constants_3.MEMBERSHIPS_LS_UPDATE] = createUpdateWorker(storage.largeSegments),
_a);
return {
put: function (mySegmentsData, payload, delay) {
updateWorkers[mySegmentsData.type].put(mySegmentsData, payload, delay);
},
stop: function () {
updateWorkers[constants_3.MEMBERSHIPS_MS_UPDATE].stop();
updateWorkers[constants_3.MEMBERSHIPS_LS_UPDATE].stop();
}
};
}
exports.MySegmentsUpdateWorker = MySegmentsUpdateWorker;
;