Fix _save_state race condition losing last_reflection timestamp
Daily and weekly timers fired simultaneously on Sundays, causing decay() and reflect() to race on _state.json. Now merges top-level keys before writing and uses atomic tempfile+rename to prevent partial reads from triggering silent JSONDecodeError fallbacks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
25792a74f4
commit
7f120f8c5c
@ -622,9 +622,30 @@ class CognitiveMemoryClient:
|
||||
return {"version": 1, "updated": "", "entries": {}}
|
||||
|
||||
def _save_state(self, state: Dict):
|
||||
"""Write _state.json."""
|
||||
"""Write _state.json atomically, merging top-level keys to prevent race conditions."""
|
||||
import tempfile
|
||||
|
||||
# Merge with existing state to preserve keys written by concurrent processes
|
||||
if self.state_path.exists():
|
||||
try:
|
||||
existing = json.loads(self.state_path.read_text())
|
||||
existing.update(state)
|
||||
state = existing
|
||||
except (json.JSONDecodeError, OSError):
|
||||
pass
|
||||
state["updated"] = datetime.now(timezone.utc).isoformat()
|
||||
self.state_path.write_text(json.dumps(state, indent=2, default=str))
|
||||
# Atomic write: write to temp file then rename
|
||||
fd, tmp_path = tempfile.mkstemp(dir=self.memory_dir, suffix=".tmp")
|
||||
try:
|
||||
with os.fdopen(fd, "w") as f:
|
||||
json.dump(state, f, indent=2, default=str)
|
||||
os.replace(tmp_path, self.state_path)
|
||||
except Exception:
|
||||
try:
|
||||
os.unlink(tmp_path)
|
||||
except OSError:
|
||||
pass
|
||||
raise
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# File I/O
|
||||
|
||||
Loading…
Reference in New Issue
Block a user