fix: remove destructive DELETE+INSERT shutdown save that caused progressive data loss

_save_all() in BaseSqliteStore did DELETE FROM table + INSERT all in-memory items
on every shutdown. Since SQLite stores use write-through caching (every CRUD writes
immediately), this was redundant. Worse, if in-memory state had fewer items than
the DB, the DELETE wiped rows and only partial data was reinserted.

- Make _save_all() a no-op (DB is always up to date via write-through)
- Replace self._save() with self._save_item() in 6 seed/default creation methods
- Remove _save_all_stores() shutdown hook (replaced with log-only message)
This commit is contained in:
2026-03-25 13:16:35 +03:00
parent 382a42755d
commit 9a3433a733
8 changed files with 17 additions and 52 deletions

View File

@@ -103,26 +103,12 @@ processor_manager = ProcessorManager(
def _save_all_stores() -> None:
"""Persist every store to disk.
"""Shutdown hook — SQLite stores use write-through caching, so this is a no-op.
Called during graceful shutdown to ensure in-memory data survives
restarts even if no CRUD happened during the session.
Every create/update/delete already goes to the database immediately.
Kept for backward compatibility with server_ref.py which calls this.
"""
all_stores = [
device_store, template_store, pp_template_store,
picture_source_store, output_target_store, pattern_template_store,
color_strip_store, audio_source_store, audio_template_store,
value_source_store, automation_store, scene_preset_store,
sync_clock_store, cspt_store, gradient_store, weather_source_store,
]
saved = 0
for store in all_stores:
try:
store._save(force=True)
saved += 1
except Exception as e:
logger.error(f"Failed to save {store._json_key} on shutdown: {e}")
logger.info(f"Shutdown save: persisted {saved}/{len(all_stores)} stores to disk")
logger.info("Shutdown: all stores already persisted (write-through cache)")
@asynccontextmanager