From 4e32709e0714e737e37986c7d856d34bf1b07fa0 Mon Sep 17 00:00:00 2001 From: Hikari Date: Fri, 6 Mar 2026 19:30:38 -0800 Subject: [PATCH] fix: prevent auto-save race condition during force sync Skip auto-save when isSyncingRef is true and reset the auto-save timer at the start of forceSync to prevent concurrent saves from sharing the same HMAC signature and causing alternating save failures. --- apps/web/src/context/GameContext.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/web/src/context/GameContext.tsx b/apps/web/src/context/GameContext.tsx index 2c11cf3..c378acf 100644 --- a/apps/web/src/context/GameContext.tsx +++ b/apps/web/src/context/GameContext.tsx @@ -154,10 +154,10 @@ export const GameProvider = ({ children }: { children: React.ReactNode }): React newlyUnlockedRef.current = []; } - // Auto-save every 30 seconds + // Auto-save every 30 seconds (skip if a force sync is in-flight to avoid signature collisions) if (Date.now() - lastSaveRef.current >= AUTO_SAVE_INTERVAL_MS) { lastSaveRef.current = Date.now(); - if (stateRef.current) { + if (stateRef.current && !isSyncingRef.current) { void saveGame({ state: stateRef.current, signature: signatureRef.current ?? undefined, @@ -203,6 +203,7 @@ export const GameProvider = ({ children }: { children: React.ReactNode }): React const forceSync = useCallback(async () => { if (!stateRef.current || isSyncingRef.current) return; isSyncingRef.current = true; + lastSaveRef.current = Date.now(); // push auto-save timer back so it doesn't fire concurrently setIsSyncing(true); try { const response = await saveGame({