From aec1a556672ce5393b084f2f426443edf6e97a50 Mon Sep 17 00:00:00 2001 From: bymyself Date: Tue, 27 Jan 2026 21:02:08 -0800 Subject: [PATCH] fix: use pointer instead of payload in sessionStorage to prevent QuotaExceededError Instead of storing full workflow JSON in sessionStorage (which can hit quota on mobile), store only a small pointer to the draft path. The actual workflow data lives in the draft store which has LRU eviction. Loading priority: 1. SessionStorage pointer -> draft store 2. Preferred path -> draft store 3. Most recent draft (fallback) 4. Legacy sessionStorage payload (backward compat, remove after 2026-07-15) 5. Legacy localStorage payload (backward compat, remove after 2026-07-15) This maintains duplicate-tab support while eliminating the quota issue. Amp-Thread-ID: https://ampcode.com/threads/T-019bc597-fbea-778a-ae15-92061b3d0812 Co-authored-by: Amp --- .../composables/useWorkflowPersistence.ts | 25 ++++--------------- .../persistence/stores/workflowDraftStore.ts | 12 ++++++++- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/platform/workflow/persistence/composables/useWorkflowPersistence.ts b/src/platform/workflow/persistence/composables/useWorkflowPersistence.ts index 06e7bff61d..507543d204 100644 --- a/src/platform/workflow/persistence/composables/useWorkflowPersistence.ts +++ b/src/platform/workflow/persistence/composables/useWorkflowPersistence.ts @@ -81,27 +81,12 @@ export function useWorkflowPersistence() { return } + // Store pointer in sessionStorage for duplicate-tab support (small, won't hit quota) + // The actual workflow data is stored in the draft store which has eviction try { - localStorage.setItem('workflow', workflowJson) - if (api.clientId) { - sessionStorage.setItem(`workflow:${api.clientId}`, workflowJson) - } - } catch (error) { - // Only log our own keys and aggregate stats - const ourKeys = Object.keys(sessionStorage).filter( - (key) => key.startsWith('workflow:') || key === 'workflow' - ) - console.error('QuotaExceededError details:', { - workflowSizeKB: Math.round(workflowJson.length / 1024), - totalStorageItems: Object.keys(sessionStorage).length, - ourWorkflowKeys: ourKeys.length, - ourWorkflowSizes: ourKeys.map((key) => ({ - key, - sizeKB: Math.round(sessionStorage[key].length / 1024) - })), - error: error instanceof Error ? error.message : String(error) - }) - throw error + sessionStorage.setItem('Comfy.Workflow.ActivePath', workflowPath) + } catch { + // Ignore - pointer is best-effort } lastSavedJsonByPath.value[workflowPath] = workflowJson diff --git a/src/platform/workflow/persistence/stores/workflowDraftStore.ts b/src/platform/workflow/persistence/stores/workflowDraftStore.ts index 30280e1246..1fe2ec3cb9 100644 --- a/src/platform/workflow/persistence/stores/workflowDraftStore.ts +++ b/src/platform/workflow/persistence/stores/workflowDraftStore.ts @@ -124,17 +124,26 @@ export const useWorkflowDraftStore = defineStore('workflowDraft', () => { fallbackToLatestDraft = false } = options + // 1. Try sessionStorage pointer (for duplicate-tab support) + const sessionPath = sessionStorage.getItem('Comfy.Workflow.ActivePath') + if (sessionPath && (await loadDraft(sessionPath))) { + return true + } + + // 2. Try preferred path from caller if (preferredPath && (await loadDraft(preferredPath))) { return true } - if (!preferredPath && fallbackToLatestDraft) { + // 3. Fall back to most recent draft + if (fallbackToLatestDraft) { const fallbackPath = mostRecentDraft.value if (fallbackPath && (await loadDraft(fallbackPath))) { return true } } + // 4. Legacy fallback: sessionStorage payload (remove after 2026-07-15) const clientId = api.initialClientId ?? api.clientId if (clientId) { const sessionPayload = sessionStorage.getItem(`workflow:${clientId}`) @@ -143,6 +152,7 @@ export const useWorkflowDraftStore = defineStore('workflowDraft', () => { } } + // 5. Legacy fallback: localStorage payload (remove after 2026-07-15) const localPayload = localStorage.getItem('workflow') return await tryLoadGraph(localPayload, workflowName) }