feat(scada): add calibrated monitoring and incident recovery
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Materialize selected burst demo months from one normal day and event runs."""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument(
|
||||
"--manifest", type=Path,
|
||||
default=Path("resources/benchmarks/tjwater2-v2-burst-demo.json"),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--generation-state", type=Path,
|
||||
default=Path("data/benchmark-generation/tjwater2-20261105/state.json"),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--state", type=Path,
|
||||
default=Path("data/benchmark-generation/tjwater2-20261105/demo-scada-state.json"),
|
||||
)
|
||||
args = parser.parse_args()
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||||
os.umask(0o077)
|
||||
|
||||
from psycopg.conninfo import make_conninfo
|
||||
from scripts.benchmark.calibration import digest, save_json
|
||||
from scripts.benchmark.generation import write_demo_scada_window
|
||||
from scripts.benchmark.simulation_design import load_simulation_design
|
||||
from scripts.check_burst_simulation_design import resolve_project
|
||||
|
||||
manifest = json.loads(args.manifest.read_text(encoding="utf-8"))
|
||||
generation = json.loads(args.generation_state.read_text(encoding="utf-8"))
|
||||
if manifest["project_code"] != generation["target"] or generation.get("status") != "prepared":
|
||||
raise ValueError("manifest and isolated generation state do not match")
|
||||
design = load_simulation_design(Path("resources/benchmarks/tjwater2-v2-burst-balanced.json"))
|
||||
source_biz, source_iot = asyncio.run(resolve_project(design))
|
||||
business_dsn = make_conninfo(source_biz, dbname=generation["target"])
|
||||
timescale_dsn = make_conninfo(source_iot, dbname=generation["target"])
|
||||
state_path = args.state.resolve()
|
||||
state_path.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
|
||||
manifest_sha256 = digest(args.manifest)
|
||||
state = json.loads(state_path.read_text(encoding="utf-8")) if state_path.exists() else {
|
||||
"version": "burst-demo-scada-state@1",
|
||||
"target": generation["target"],
|
||||
"manifest_sha256": manifest_sha256,
|
||||
"cases": {},
|
||||
"status": "materializing",
|
||||
}
|
||||
if state["target"] != generation["target"] or state["manifest_sha256"] != manifest_sha256:
|
||||
raise ValueError("demo state belongs to different inputs")
|
||||
save_json(state_path, state)
|
||||
normal_source_start = datetime.fromisoformat(manifest["normal_source_start"])
|
||||
for case in manifest["cases"]:
|
||||
source_case = generation["cases"].get(case["case_key"])
|
||||
if not source_case or source_case.get("status") != "scada_materialized":
|
||||
raise ValueError(f"event source is unavailable: {case['case_key']}")
|
||||
summary = write_demo_scada_window(
|
||||
business_dsn=business_dsn,
|
||||
timescale_dsn=timescale_dsn,
|
||||
normal_source_start=normal_source_start,
|
||||
target_start=datetime.fromisoformat(case["target_start"]),
|
||||
day_count=int(manifest["day_count"]),
|
||||
event_start=datetime.fromisoformat(case["event_start"]),
|
||||
event_run_id=source_case["analysis_run_id"],
|
||||
noise_seed=manifest["noise_seed"],
|
||||
)
|
||||
state["cases"][case["demo_id"]] = {
|
||||
"case_key": case["case_key"],
|
||||
"entry_mode": case["entry_mode"],
|
||||
**summary,
|
||||
}
|
||||
save_json(state_path, state)
|
||||
print({"demo_id": case["demo_id"], "rows": summary["rows"]}, flush=True)
|
||||
state["status"] = "completed"
|
||||
save_json(state_path, state)
|
||||
print(json.dumps({"status": state["status"], "cases": state["cases"]}, ensure_ascii=False), flush=True)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user