"""Concurrency check of web/store.py wjson/rjson: one thread rewrites a job file while another reads it. Reproduces the 2026-10-12 E2E failure (reader saw an empty file during write_text). Pass = no read errors and no writer errors. usage: python test_store_concurrency.py [writes] """ import sys import tempfile import threading import time from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "web")) import store # noqa: E402 N = int(sys.argv[1]) if len(sys.argv) > 1 else 500 p = Path(tempfile.mkdtemp()) / "G1_job.json" store.wjson(p, {"state": "대기", "log": []}) stop = threading.Event() read_err, reads = [], [0] def reader(): while not stop.is_set(): try: store.rjson(p) reads[0] += 1 except Exception as e: read_err.append(repr(e)) t = threading.Thread(target=reader, daemon=True) t.start() write_err, t0 = [], time.time() try: for i in range(N): try: store.wjson(p, {"state": "실행 중", "log": ["x" * 200] * (i % 50)}) except Exception as e: write_err.append(repr(e)) finally: stop.set() t.join(5) print(f"writes {N} reads {reads[0]} read_errors {len(read_err)} write_errors {len(write_err)} " f"{time.time() - t0:.1f}s", read_err[:2], write_err[:2]) sys.exit(0 if not read_err and not write_err else 1)