from __future__ import annotations import argparse import fcntl from pathlib import Path import sys sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from main import engine from wehago_compare import ( _build_db_state_signature, _ensure_year_export_row_cache, _get_fast_year_export_row_cache_signature, _load_snapshot_status_map, _project_year_export_row_cache_from_latest_resolved, _rebuild_compare_query_projection, _refresh_year_resolved_sections, _status_row_counts_from_sections, _upsert_snapshot_status, ) def parse_range(value: str) -> tuple[int, int]: raw = str(value or "").strip() if "-" not in raw: year = int(raw) return year, year left, right = raw.split("-", 1) start_year = int(left) end_year = int(right) if start_year > end_year: start_year, end_year = end_year, start_year return start_year, end_year def main() -> None: parser = argparse.ArgumentParser(description="Rebuild WEHAGO compare snapshots and query projections.") parser.add_argument("--years", nargs="*", type=int, default=[]) parser.add_argument("--fast-years", nargs="*", type=int, default=[]) parser.add_argument("--ranges", nargs="*", default=[]) args = parser.parse_args() lock_path = Path("/tmp/wehago_compare_compute.lock") lock_path.parent.mkdir(parents=True, exist_ok=True) with lock_path.open("w") as lock_file: fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX) with engine.connect().execution_options(isolation_level="AUTOCOMMIT") as conn: for year in sorted({int(year) for year in args.fast_years if int(year or 0) > 0}): signature = _build_db_state_signature(conn, year, year) print({"step": "fast_year_projection_start", "year": year, "signature": signature}, flush=True) projected = _project_year_export_row_cache_from_latest_resolved(conn, year, signature) if not projected: print({"step": "fast_year_projection_miss", "year": year}, flush=True) selected_signature = _ensure_year_export_row_cache(conn, year) else: selected_signature = _get_fast_year_export_row_cache_signature(conn, year) if selected_signature: _upsert_snapshot_status( conn, year, signature=selected_signature, state="ready", row_counts={}, built_now=True, ) else: _upsert_snapshot_status( conn, year, signature=signature, state="ready", row_counts={}, built_now=True, ) print( { "step": "fast_year_projection_done", "year": year, "selected_signature": selected_signature, }, flush=True, ) for year in sorted({int(year) for year in args.years if int(year or 0) > 0}): signature = _build_db_state_signature(conn, year, year) print({"step": "year_snapshot_start", "year": year, "signature": signature}, flush=True) _refresh_year_resolved_sections(conn, year) print({"step": "year_snapshot_done", "year": year}, flush=True) for start_year, end_year in [parse_range(item) for item in args.ranges]: print({"step": "projection_start", "start_year": start_year, "end_year": end_year}, flush=True) counts, snapshot_state = _rebuild_compare_query_projection(engine, conn, start_year, end_year) print( { "step": "projection_done", "start_year": start_year, "end_year": end_year, "counts": counts, "snapshot_state": snapshot_state, }, flush=True, ) if __name__ == "__main__": main()