UNPKG

@splitsoftware/splitio-commons

Version:
125 lines (124 loc) 6.17 kB
"use strict"; 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;