some fixes

This commit is contained in:
Ayzen
2026-06-05 14:40:10 +03:00
parent 22942d9dc9
commit bbea744459
35 changed files with 1797 additions and 297 deletions
+16 -2
View File
@@ -3,6 +3,7 @@
from __future__ import annotations
import json
import os
from pathlib import Path
from python_app.models.run_config_model import RunConfigModel, parse_combos_from_text
@@ -41,12 +42,25 @@ class ConfigWriter:
asset.bundle_path = str(bundle_path)
def write(self, config: RunConfigModel, output_path: Path) -> Path:
"""Write run configuration JSON file."""
"""Atomically write run configuration JSON file.
Mirrors ProcessingLiveConfigWriter: dump to a sibling .tmp, flush+fsync to
durably commit the bytes, then os.replace() onto the destination. The replace
is atomic, so a C++ consumer can never observe a half-written config (which
would abort it with an opaque JSON parse error), even across a crash or power
loss mid-write on the SD-card-backed Pi.
"""
output_path.parent.mkdir(parents=True, exist_ok=True)
# allow_nan=False: a stray NaN/Infinity must fail loudly here in Python
# rather than serialize to a non-standard token that aborts every C++
# consumer at startup with an opaque JSON parse error.
output_path.write_text(json.dumps(config.to_dict(), indent=2, allow_nan=False), encoding="utf-8")
serialized = json.dumps(config.to_dict(), indent=2, allow_nan=False)
tmp_path = output_path.with_suffix(output_path.suffix + ".tmp")
with open(tmp_path, "w", encoding="utf-8") as handle:
handle.write(serialized)
handle.flush()
os.fsync(handle.fileno())
os.replace(tmp_path, output_path)
return output_path