fix simulation reporting and research resilience
This commit is contained in:
+37
-14
@@ -17,6 +17,7 @@ from app.services.census import CensusService
|
||||
from app.services.i18n import locale_from_request, translate
|
||||
from app.services.sim_logger import SimulationLogger
|
||||
from app.services.simulation_logging import bind_simulation, unbind_simulation
|
||||
from app.services.narrator import REPORT_SCHEMA_VERSION
|
||||
|
||||
from enum import Enum
|
||||
|
||||
@@ -213,8 +214,11 @@ async def simulate(req: SimulateRequest, request: Request):
|
||||
"模拟 %s:居民生成完成,耗时=%.2f秒,实际数量=%d",
|
||||
sim_id, time.monotonic() - t_stage, len(agents),
|
||||
)
|
||||
fallback_count = sum(1 for agent in agents if agent.generation_source != "llm")
|
||||
await store.set_meta(sim_id, "citizen_generation_fallback_count", fallback_count)
|
||||
sim_log.log_event("citizens_generated", {
|
||||
"count": len(agents),
|
||||
"fallback_count": fallback_count,
|
||||
"elapsed_s": round(time.monotonic() - t_stage, 3),
|
||||
})
|
||||
t_stage = time.monotonic()
|
||||
@@ -449,10 +453,10 @@ async def get_report(sim_id: str, request: Request):
|
||||
|
||||
# Cancelled: client should not keep polling, but partial data (if any) is
|
||||
# still in the report table. Try to return it before bailing.
|
||||
if sim.get("status") == "cancelled":
|
||||
result = await store.get_report(sim_id)
|
||||
if result.get("status") == "ready":
|
||||
return result["report"]
|
||||
if sim.get("status") == "cancelled":
|
||||
result = await store.get_report(sim_id)
|
||||
if result.get("status") == "ready":
|
||||
return result["report"]
|
||||
return {"status": "cancelled", "message": translate("simulation_cancelled", locale)}
|
||||
|
||||
# Interrupted (typically because the backend restarted and the pipeline
|
||||
@@ -468,12 +472,27 @@ async def get_report(sim_id: str, request: Request):
|
||||
"message": translate("simulation_interrupted_no_report", locale),
|
||||
}
|
||||
|
||||
result = await store.get_report(sim_id)
|
||||
if result.get("status") == "ready":
|
||||
report = result["report"]
|
||||
report["rules_text"] = sim.get("rules_text", "") or ""
|
||||
return report
|
||||
return result
|
||||
result = await store.get_report(sim_id)
|
||||
if (
|
||||
result.get("status") == "ready"
|
||||
and result.get("report", {}).get("report_schema_version") == REPORT_SCHEMA_VERSION
|
||||
):
|
||||
report = result["report"]
|
||||
report["rules_text"] = sim.get("rules_text", "") or ""
|
||||
return report
|
||||
if result.get("status") == "ready":
|
||||
# A completed simulation may have a cached report from an older
|
||||
# schema. Regenerate it once so report changes are not invisible to
|
||||
# users who already ran the simulation.
|
||||
narrator = getattr(request.app.state, "narrator", None)
|
||||
if narrator is not None and hasattr(narrator, "set_locale"):
|
||||
narrator.set_locale(locale)
|
||||
report = await request.app.state.narrator.generate_report(sim_id, store)
|
||||
if "error" not in report:
|
||||
await store.save_report(sim_id, report)
|
||||
report["rules_text"] = sim.get("rules_text", "") or ""
|
||||
return report
|
||||
return result
|
||||
|
||||
|
||||
@router.post("/simulation/{sim_id}/publish")
|
||||
@@ -513,10 +532,14 @@ async def compare(sim_id: str, fork_id: str, request: Request):
|
||||
source_agents = await store.get_all_agents(sim_id)
|
||||
fork_agents = await store.get_all_agents(fork_id)
|
||||
|
||||
async def _get_or_generate_report(sid):
|
||||
cached = await store.get_report(sid)
|
||||
if cached and cached.get("status") == "ready":
|
||||
return cached["report"]
|
||||
async def _get_or_generate_report(sid):
|
||||
cached = await store.get_report(sid)
|
||||
if (
|
||||
cached
|
||||
and cached.get("status") == "ready"
|
||||
and cached.get("report", {}).get("report_schema_version") == REPORT_SCHEMA_VERSION
|
||||
):
|
||||
return cached["report"]
|
||||
rpt = await narrator.generate_report(sid, store)
|
||||
if "error" not in rpt:
|
||||
await store.save_report(sid, rpt)
|
||||
|
||||
Reference in New Issue
Block a user