From ff64cf5063b610d4ea56392158ed00e29ef20fdf Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Thu, 28 Aug 2025 13:30:57 +0200 Subject: [PATCH] Fix a cache race condition in local backed session storage (#16177) * fix: cache race condition * fix: typo and order * feat: tweak log message --- .../local-backed-session-storage.service.ts | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/apps/browser/src/platform/services/local-backed-session-storage.service.ts b/apps/browser/src/platform/services/local-backed-session-storage.service.ts index 978b993fa4d..9e808de0fd0 100644 --- a/apps/browser/src/platform/services/local-backed-session-storage.service.ts +++ b/apps/browser/src/platform/services/local-backed-session-storage.service.ts @@ -73,8 +73,29 @@ export class LocalBackedSessionStorageService const value = await this.getLocalSessionValue(await this.sessionKey.get(), key); - this.cache[key] = value; - return value as T; + if (this.cache[key] === undefined && value !== undefined) { + // Cache is still empty and we just got a value from local/session storage, cache it. + this.cache[key] = value; + return value as T; + } else if (this.cache[key] === undefined && value === undefined) { + // Cache is still empty and we got nothing from local/session storage, no need to modify cache. + return value as T; + } else if (this.cache[key] !== undefined && value !== undefined) { + // Conflict, somebody wrote to the cache while we were reading from storage + // but we also got a value from storage. We assume the cache is more up to date + // and use that value. + this.logService.warning( + `Conflict while reading from local session storage, both cache and storage have values. Key: ${key}. Using cached value.`, + ); + return this.cache[key] as T; + } else if (this.cache[key] !== undefined && value === undefined) { + // Cache was filled after the local/session storage read completed. We got null + // from the storage read, but we have a value from the cache, use that. + this.logService.warning( + `Conflict while reading from local session storage, cache has value but storage does not. Key: ${key}. Using cached value.`, + ); + return this.cache[key] as T; + } } async has(key: string): Promise {