refactor(persistence): 24 hand-rolled atomic JSON/text writers go through utils.atomic_json_write / atomic_write_text
Each copy re-implemented temp+replace by hand and lacked one or more of fsync, symlink preservation, atomic_replace's Windows-contention retry and EXDEV/bind-mount fallback, mode preservation, or interrupt-safe temp cleanup. Three (gateway/session_persistence, cron/suggestions, agent/shell_hooks) were verbatim inlines of utils._atomic_write; two modules defined their own directory-fsync helper, now utils.fsync_directory. plugins/google_meet/_jsonfile.write_json_atomic is deleted (callers use the canonical helper directly). Behavior change: every one of these writers now fsyncs the payload, keeps a pre-existing target's mode, cleans its temp file on BaseException, and survives Windows AV/indexer contention and cross-device renames the way config writes already did. cron/suggestions.json is 0600 from creation (previously chmod'ed after the replace). Skipped on purpose: cron/jobs.py two-phase staging, gateway/status._write_json_excl (create-only lock), kanban_transfer staging (not atomic writers); tools/skill_usage. _write_suppressed_names lives inside a PLUGIN-COMPAT block.
This commit is contained in:
@@ -1591,15 +1591,12 @@ def import_profile(archive_path: str, name: Optional[str] = None) -> Path:
|
||||
# Rename
|
||||
|
||||
def _atomic_write_json(path: Path, data: dict) -> bool:
|
||||
"""Write *data* to *path* via a sibling ``.tmp`` + rename. Returns False (tmp cleaned) on OSError."""
|
||||
tmp = path.with_suffix(path.suffix + ".tmp")
|
||||
"""Atomic rewrite of a third-party JSON config; False on OSError (nothing partially written)."""
|
||||
from utils import atomic_json_write
|
||||
try:
|
||||
tmp.write_text(json.dumps(data, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
|
||||
tmp.replace(path)
|
||||
atomic_json_write(path, data)
|
||||
return True
|
||||
except OSError:
|
||||
with contextlib.suppress(OSError):
|
||||
tmp.unlink(missing_ok=True)
|
||||
return False
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user