From 304d5b85ef36847e27a769e82db9095cb11e483e Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 8 Jun 2026 18:05:14 +0530 Subject: [PATCH] fix: revalidate cache after cable subscription --- app/javascript/dashboard/App.vue | 17 +++++++++++------ .../shared/helpers/BaseActionCableConnector.js | 10 ++++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/app/javascript/dashboard/App.vue b/app/javascript/dashboard/App.vue index 29a252a3b..b74f0ce7b 100644 --- a/app/javascript/dashboard/App.vue +++ b/app/javascript/dashboard/App.vue @@ -109,19 +109,24 @@ export default { this.$store.dispatch('setActiveAccount', { accountId: this.currentAccountId, }); - // Seed Vuex from IndexedDB before ActionCable connects so warm boots - // paint cached config (inboxes, labels, teams, canned responses, agents) - // instantly. Stale entries are revalidated in the background against the - // server's authoritative cache keys. + const { pubsub_token: pubsubToken } = this.currentUser || {}; + const actionCable = vueActionCable.init(this.store, pubsubToken); + + // Seed Vuex from IndexedDB while ActionCable connects so warm boots paint + // cached config instantly. Once the cable subscription is confirmed, run + // one more reconciliation to catch invalidations broadcast between the + // first cache-key snapshot and the active subscription. await hydrateStoresFromCache(this.$store, this.currentAccountId); + actionCable.connected.then(() => { + hydrateStoresFromCache(this.$store, this.currentAccountId); + }); + const account = this.getAccount(this.currentAccountId); const { locale, latest_chatwoot_version: latestChatwootVersion } = account; - const { pubsub_token: pubsubToken } = this.currentUser || {}; // If user locale is set, use it; otherwise use account locale this.setLocale(this.uiSettings?.locale || locale); this.latestChatwootVersion = latestChatwootVersion; - vueActionCable.init(this.store, pubsubToken); this.reconnectService = new ReconnectService(this.store, this.router); window.reconnectService = this.reconnectService; diff --git a/app/javascript/shared/helpers/BaseActionCableConnector.js b/app/javascript/shared/helpers/BaseActionCableConnector.js index 06f529dde..846c815cd 100644 --- a/app/javascript/shared/helpers/BaseActionCableConnector.js +++ b/app/javascript/shared/helpers/BaseActionCableConnector.js @@ -14,6 +14,9 @@ class BaseActionCableConnector { ) { const websocketURL = websocketHost ? `${websocketHost}/cable` : undefined; + this.connected = new Promise(resolve => { + this.resolveConnected = resolve; + }); this.consumer = createConsumer(websocketURL); this.subscription = this.consumer.subscriptions.create( { @@ -26,6 +29,10 @@ class BaseActionCableConnector { updatePresence() { this.perform('update_presence'); }, + connected: () => { + this.resolveConnected(); + this.onConnected(); + }, received: this.onReceived, disconnected: () => { BaseActionCableConnector.isDisconnected = true; @@ -74,6 +81,9 @@ class BaseActionCableConnector { }, RECONNECT_INTERVAL); }; + // eslint-disable-next-line class-methods-use-this + onConnected = () => {}; + // eslint-disable-next-line class-methods-use-this onReconnect = () => {};