From 65bce2c52dfff859abd7ce64e36baf1a21d452d8 Mon Sep 17 00:00:00 2001 From: CC Worker Date: Sun, 31 May 2026 21:09:38 +0000 Subject: [PATCH] fix(auto-save): dirty-flag pattern in SharedStoreService Replaces JSON.stringify snapshot comparison with a store.listen() dirty flag. Eliminates 5-15ms main-thread serialize on every poll tick when canvas is idle. --- src/services/tldraw/sharedStoreService.ts | 28 ++++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/services/tldraw/sharedStoreService.ts b/src/services/tldraw/sharedStoreService.ts index 7e8710f..63eec36 100644 --- a/src/services/tldraw/sharedStoreService.ts +++ b/src/services/tldraw/sharedStoreService.ts @@ -19,12 +19,17 @@ export class SharedStoreService { private lastSaveTime: number = Date.now(); private autoSaveInterval: ReturnType | null = null; private config: AutoSaveConfig; + private isDirty = false; + private dirtyListener: (() => void) | null = null; constructor(private store: TLStore, config?: Partial) { this.config = { ...DEFAULT_CONFIG, ...config }; + this.dirtyListener = store.listen(() => { + this.isDirty = true; + }); logger.debug('shared-store-service', '๐Ÿ—๏ธ Initializing SharedStoreService'); } @@ -52,18 +57,16 @@ export class SharedStoreService { } private async checkAndSave(setLoadingState: (state: LoadingState) => void): Promise { - const now = Date.now(); - if (now - this.lastSaveTime >= this.config.saveInterval) { - const currentSnapshot = getSnapshot(this.store); - const savedSnapshot = storageService.get(StorageKeys.LOCAL_SNAPSHOT); + if (!this.isDirty) { + return; + } - if (!savedSnapshot || JSON.stringify(currentSnapshot) !== JSON.stringify(savedSnapshot)) { - logger.debug('shared-store-service', '๐Ÿ’พ Auto-saving snapshot - changes detected'); - await this.saveSnapshot(currentSnapshot, setLoadingState); - this.lastSaveTime = now; - } else { - logger.trace('shared-store-service', '๐Ÿ“ No changes detected, skipping auto-save'); - } + this.isDirty = false; + const now = Date.now(); + + if (now - this.lastSaveTime >= this.config.saveInterval) { + await this.saveSnapshot(getSnapshot(this.store), setLoadingState); + this.lastSaveTime = now; } } @@ -109,7 +112,10 @@ export class SharedStoreService { public clear(): void { this.stopAutoSave(); + this.dirtyListener?.(); + this.dirtyListener = null; this.store.clear(); + this.isDirty = false; logger.debug('shared-store-service', '๐Ÿงน Store cleared'); } }