A02: Atomic cooldown state with exclusive lock and flush

- _write_state: write to temp file, fsync, rename atomically
- Acquire exclusive lock before any file operations
- Flush and fsync before unlock to prevent data loss
- Remove stale .tmp file after successful write
- Add test for atomic write behavior
- 109 Python tests pass
This commit is contained in:
ik
2026-09-10 06:10:35 +07:00
parent 779d554057
commit 79245965ec
2 changed files with 28 additions and 2 deletions
+11 -2
View File
@@ -6,6 +6,7 @@ import json
import os
import sys
import time
import tempfile
from dataclasses import asdict
from pathlib import Path
from urllib.parse import urlsplit
@@ -55,14 +56,22 @@ def _read_state(state_file: Path) -> dict:
def _write_state(state_file: Path, state: dict) -> None:
"""Write state file atomically with exclusive lock."""
"""A02: Atomic write with exclusive lock, flush before unlock.
Writes to temp file first, then renames atomically. Lock is acquired
before any file operations to prevent race conditions.
"""
state_file.parent.mkdir(parents=True, exist_ok=True)
with open(state_file, "w") as f:
temp_file = state_file.with_suffix(".tmp")
with open(temp_file, "w") as f:
fcntl.flock(f, fcntl.LOCK_EX)
try:
f.write(json.dumps(state, sort_keys=True))
f.flush()
os.fsync(f.fileno())
finally:
fcntl.flock(f, fcntl.LOCK_UN)
temp_file.replace(state_file)
def fetch_site_key(url: str) -> str: