Repository navigation
Relay simulation run stage and progress on computing economy responses - #3916
Merged
Merged
Conversation
While an annual economy run is computing, the economy route now relays the optional stage fields that the simulation entrypoint reports for the job (PolicyEngine/policyengine-sim-api#781): stage, progress, progress_max, submitted_at, started_at, stage_started_at and segments. Malformed fields are dropped and never fail a poll. Completed, error and field-less computing bodies keep their existing shape. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 13, 2026
Merged
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3916 +/- ##
===========================================
+ Coverage 45.27% 87.62% +42.35%
===========================================
Files 183 198 +15
Lines 11084 12248 +1164
Branches 1907 2163 +256
===========================================
+ Hits 5018 10732 +5714
+ Misses 5644 920 -4724
- Partials 422 596 +174 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
anth-volk
reviewed
Oct 14, 2026
anth-volk
left a comment
Collaborator
There was a problem hiding this comment.
Two typing comments and one mismatch between the description and the response bodies, from a review against PolicyEngine/policyengine-sim-api#781.
…on-run-progress # Conflicts: # policyengine_api/libs/simulation_entrypoint.py # policyengine_api/services/economy_service.py
Review follow-up: - EconomicImpactResult.run_progress is now SimulationRunProgress | None, and the route calls to_dict() once. The service passes execution.run_progress through without getattr or isinstance, so a wrong type fails loudly instead of dropping the fields. Test doubles for computing results now carry run_progress. - submitted_at, started_at and stage_started_at are AwareDatetime, so a malformed timestamp drops the stage fields; they still serialise as ISO 8601. - A test pins the body for a job whose worker reports no stages: once policyengine-sim-api#781 deploys, it still gains submitted_at. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
marked this pull request as ready for review
October 15, 2026 19:02
This was referenced Oct 15, 2026
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
While an annual economy run is computing,
GET /<country_id>/economy/<policy_id>/over/<baseline_policy_id>now relays the optional stage fields that the simulation entrypoint reports for the job (PolicyEngine/policyengine-sim-api#781). Clients can show real progress instead of elapsed time divided by a fixed duration.Related: #2001. That issue was deferred to the API v2 calculation migration, with the note that progress should come from coarse, monotonic calculation stages on an asynchronous path. policyengine-sim-api#781 adds those stages to the simulation entrypoint's job status. This PR only relays them for the asynchronous economy route. The synchronous household endpoint is unchanged and stays indeterminate.
Response
A computing body on a worker that reports stages:
{ "status": "computing", "message": null, "result": null, "stage": "reform", "progress": 67, "progress_max": 96, "submitted_at": "2026-10-13T12:00:00Z", "started_at": "2026-10-13T12:00:30Z", "stage_started_at": "2026-10-13T12:01:00Z" }A segmented US national run also returns
"segments": {"completed": 19, "total": 20}.Unchanged bodies:
Once #781's gateway deploys, it reports
submitted_atfor every new job. Jobs routed to worker apps without stage reporting therefore gain that one field and no others. This is additive, and a test pins it.Changes
libs/simulation_entrypoint.py:SimulationRunProgressreadsstage,progress,progress_max,submitted_at,started_at,stage_started_atandsegmentsfromGET /jobs/{job_id}. The timestamps areAwareDatetime.ModalSimulationExecution.run_progressholds it. Malformed values giveNoneand never fail a poll.stageis a plain string, because later entrypoint versions may add stages.services/economy_service.py:EconomicImpactResult.run_progressisSimulationRunProgress | Noneand comes straight from the running branch of_handle_execution_state. It is not part ofto_dict(), so existing callers see no change.routes/economy_routes.py: callsrun_progress.to_dict()and merges the fields only when the status iscomputingand the fields are present.openapi_spec.yaml: documents the optional fields on the annual route.changelog.d:addedfragment.The completion fields (
finished_at,stage_durations) are not relayed: completed results come from thereform_impacttable, not from a live poll.Migration notes
economy, annual route only. It stays on the Flask/API v1 path.scripts/export_migration_contracts.pyproduced no diff, and the stable response fields are unchanged.Merge order
Merge after policyengine-sim-api#781 is merged and verified on beta. This PR changes no response until then.
Testing
pytest tests/unit tests/contract: 2,391 passed after merging currentmaster._handle_execution_state, and the route bodies (computing with and without fields, completed results).python scripts/run_quality_guards.py: passed.ruff format --check .andruff checkon the changed files: passed.Downstream
policyengine-app-v2 can read
progressandprogress_maxinSocietyWideCalcStrategy: move its time-based estimate between the two values, never backwards, and name thestagein theRunProgresscaption.🤖 Generated with Claude Code