UNPKG

@mtdt.temp/browser-core

Version:
123 lines 5.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LOCK_EXPIRATION_DELAY = exports.LOCK_MAX_TRIES = exports.LOCK_RETRY_DELAY = void 0; exports.processSessionStoreOperations = processSessionStoreOperations; exports.createLock = createLock; const timer_1 = require("../../tools/timer"); const stringUtils_1 = require("../../tools/utils/stringUtils"); const timeUtils_1 = require("../../tools/utils/timeUtils"); const telemetry_1 = require("../telemetry"); const sessionState_1 = require("./sessionState"); exports.LOCK_RETRY_DELAY = 10; exports.LOCK_MAX_TRIES = 100; // Locks should be hold for a few milliseconds top, just the time it takes to read and write a // cookie. Using one second should be enough in most situations. exports.LOCK_EXPIRATION_DELAY = timeUtils_1.ONE_SECOND; const LOCK_SEPARATOR = '--'; const bufferedOperations = []; let ongoingOperations; function processSessionStoreOperations(operations, sessionStoreStrategy, numberOfRetries = 0) { var _a; const { isLockEnabled, persistSession, expireSession } = sessionStoreStrategy; const persistWithLock = (session) => persistSession({ ...session, lock: currentLock }); const retrieveStore = () => { const { lock, ...session } = sessionStoreStrategy.retrieveSession(); return { session, lock: lock && !isLockExpired(lock) ? lock : undefined, }; }; if (!ongoingOperations) { ongoingOperations = operations; } if (operations !== ongoingOperations) { bufferedOperations.push(operations); return; } if (isLockEnabled && numberOfRetries >= exports.LOCK_MAX_TRIES) { (0, telemetry_1.addTelemetryDebug)('Aborted session operation after max lock retries', { currentStore: retrieveStore(), }); next(sessionStoreStrategy); return; } let currentLock; let currentStore = retrieveStore(); if (isLockEnabled) { // if someone has lock, retry later if (currentStore.lock) { retryLater(operations, sessionStoreStrategy, numberOfRetries); return; } // acquire lock currentLock = createLock(); persistWithLock(currentStore.session); // if lock is not acquired, retry later currentStore = retrieveStore(); if (currentStore.lock !== currentLock) { retryLater(operations, sessionStoreStrategy, numberOfRetries); return; } } let processedSession = operations.process(currentStore.session); if (isLockEnabled) { // if lock corrupted after process, retry later currentStore = retrieveStore(); if (currentStore.lock !== currentLock) { retryLater(operations, sessionStoreStrategy, numberOfRetries); return; } } if (processedSession) { if ((0, sessionState_1.isSessionInExpiredState)(processedSession)) { expireSession(processedSession); } else { (0, sessionState_1.expandSessionState)(processedSession); if (isLockEnabled) { persistWithLock(processedSession); } else { persistSession(processedSession); } } } if (isLockEnabled) { // correctly handle lock around expiration would require to handle this case properly at several levels // since we don't have evidence of lock issues around expiration, let's just not do the corruption check for it if (!(processedSession && (0, sessionState_1.isSessionInExpiredState)(processedSession))) { // if lock corrupted after persist, retry later currentStore = retrieveStore(); if (currentStore.lock !== currentLock) { retryLater(operations, sessionStoreStrategy, numberOfRetries); return; } persistSession(currentStore.session); processedSession = currentStore.session; } } // call after even if session is not persisted in order to perform operations on // up-to-date session state value => the value could have been modified by another tab (_a = operations.after) === null || _a === void 0 ? void 0 : _a.call(operations, processedSession || currentStore.session); next(sessionStoreStrategy); } function retryLater(operations, sessionStore, currentNumberOfRetries) { (0, timer_1.setTimeout)(() => { processSessionStoreOperations(operations, sessionStore, currentNumberOfRetries + 1); }, exports.LOCK_RETRY_DELAY); } function next(sessionStore) { ongoingOperations = undefined; const nextOperations = bufferedOperations.shift(); if (nextOperations) { processSessionStoreOperations(nextOperations, sessionStore); } } function createLock() { return (0, stringUtils_1.generateUUID)() + LOCK_SEPARATOR + (0, timeUtils_1.timeStampNow)(); } function isLockExpired(lock) { const [, timeStamp] = lock.split(LOCK_SEPARATOR); return !timeStamp || (0, timeUtils_1.elapsed)(Number(timeStamp), (0, timeUtils_1.timeStampNow)()) > exports.LOCK_EXPIRATION_DELAY; } //# sourceMappingURL=sessionStoreOperations.js.map