From b8bca46ba86c87e54d14549d5e8a3b6a633b9969 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 29 May 2026 16:28:19 +0530 Subject: [PATCH] fix: address cache revalidation feedback --- .../dashboard/api/CacheEnabledApiClient.js | 34 +++++++++++++++---- .../helper/CacheHelper/DataManager.js | 6 ++-- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/app/javascript/dashboard/api/CacheEnabledApiClient.js b/app/javascript/dashboard/api/CacheEnabledApiClient.js index a58ee5163..2002a3a73 100644 --- a/app/javascript/dashboard/api/CacheEnabledApiClient.js +++ b/app/javascript/dashboard/api/CacheEnabledApiClient.js @@ -25,6 +25,13 @@ class CacheEnabledApiClient extends ApiClient { return axios.get(this.url); } + async getCacheKeyFromServer() { + const response = await axios.get( + `/api/v1/accounts/${this.accountIdFromRoute}/cache_keys` + ); + return response.data.cache_keys?.[this.cacheModelName] ?? null; + } + // eslint-disable-next-line class-methods-use-this extractDataFromResponse(response) { return response.data.payload; @@ -57,10 +64,16 @@ class CacheEnabledApiClient extends ApiClient { return this.marshallData(localData); } - // Empty IDB (first load or wiped): seed from network using whatever local - // cache key we have (null when never seen). refetchAndCommit handles null. - const localKey = await this.dataManager.getCacheKey(this.cacheModelName); - return this.refetchAndCommit(localKey); + // Empty IDB (first load or wiped): capture the authoritative key before + // persisting rows so future boots can revalidate this cached data. + let serverKey = null; + try { + serverKey = await this.getCacheKeyFromServer(); + } catch { + // Ignore error. The network fetch below should still work, and storing + // null keeps this cache eligible for boot-time revalidation later. + } + return this.refetchAndCommit(serverKey); } async refetchAndCommit(newKey = null) { @@ -77,7 +90,7 @@ class CacheEnabledApiClient extends ApiClient { }); await this.dataManager.setCacheKeys({ - [this.cacheModelName]: newKey, + [this.cacheModelName]: newKey === undefined ? null : newKey, }); } catch { // Ignore error @@ -91,8 +104,15 @@ class CacheEnabledApiClient extends ApiClient { await this.dataManager.initDb(); } - const cachekey = await this.dataManager.getCacheKey(this.cacheModelName); - return cacheKeyFromApi === cachekey; + const cacheKey = await this.dataManager.getCacheKey(this.cacheModelName); + if (cacheKey === undefined) { + const localData = await this.dataManager.get({ + modelName: this.cacheModelName, + }); + return localData.length === 0; + } + + return cacheKeyFromApi === cacheKey; } } diff --git a/app/javascript/dashboard/helper/CacheHelper/DataManager.js b/app/javascript/dashboard/helper/CacheHelper/DataManager.js index 22be6cbde..6be2b7b06 100644 --- a/app/javascript/dashboard/helper/CacheHelper/DataManager.js +++ b/app/javascript/dashboard/helper/CacheHelper/DataManager.js @@ -19,9 +19,9 @@ export class DataManager { // first install, so fresh devices skip this. Clearing before creating // means we only ever clear stores that pre-existed this upgrade. if (oldVersion > 0) { - [...db.objectStoreNames].forEach(name => - tx.objectStore(name).clear() - ); + for (let index = 0; index < db.objectStoreNames.length; index += 1) { + tx.objectStore(db.objectStoreNames.item(index)).clear(); + } } if (!db.objectStoreNames.contains('cache-keys')) {