Repository navigation
Archive rounds through the hosted job API (Modal 150s ceiling) - #236
Merged
Merged
Conversation
Modal answers any web request past 150s with HTTP 303, and a 6000-draw forecast_uk takes ~5.5 minutes on a cold container, so the archive run 42963724470 (due for the 12 Nov GDP release) failed with "Redirect to .../mcp not followed" after ~160s. Following the 303 cannot work: it turns the POST into a GET, which Modal's result URL rejects. nowcast.py now starts svar_forecast (forecast_uk's adapter) with start_job and collects it with 30s get_job_result polls: transport errors on a poll are retried, a job error is fatal, and it gives up with the job id after 17 minutes, inside the step's 20. svar_forecast joins jobs.JOB_TOOLS, so the server needs the redeploy that merging this triggers; until then the script says so instead of failing obscurely. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
streamablehttp_client and ClientSession both run anyio task groups, which wrap anything raised inside them in an ExceptionGroup. A HostedToolError raised in there reached run_as_job as a transport error, so a failed job was retried and the "Redeploy" message could never print. Judge the reply after both contexts close, and test it through real task groups. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vahid-ahmadi
marked this pull request as ready for review
November 11, 2026 10:24
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.
Cause
Archive a forecast round before release, run 42963724470 (11 Nov, main
e84d8c19):--due 3passed:2026-11-12 uk_gdp_cvm. The release calendar was not stale on this run.--edge-gatepassed:hosted data edge 2026Q2 >= 2026Q2; a new round is possible.forecasts/nowcast.py --draws 6000, which callsforecast_ukdirectly on the hosted server. The step started at 05:08:26 and failed at 05:11:04:Modal answers any web-endpoint request that runs past 150 s with HTTP 303. A 6000-draw
forecast_uktakes about 5.5 minutes on a cold container, by the workflow's own measured comment, and the direct call now fails at the ceiling. The same direct call did complete in August (12–13 and 17–19 Aug, pertest_nowcast_edge_gate.py), so either the server or Modal's handling of long requests has changed since then; either way the direct route is no longer usable.Following the redirect is not a fix:
400 modal-http: bad redirect method. That was measured when the job API was built; seeintegration/src/policyengine_macro/jobs.py.Fix
Client:
forecasts/nowcast.py. It now does whatscore_reformcallers already do:start_job(tool="svar_forecast", arguments={horizons, draws}), thenget_job_resultpolls withwait_seconds=30.Server:
jobs.JOB_TOOLSgainssvar_forecast, the adapter behindforecast_uk. Thestart_jobdescription now mentions it.core.svar_forecastenforces the samedraws/horizonsbounds as the tool (_bounded_int), so the job path does not widen what a caller can request. The deploy copiesintegration/from the checked-out commit (add_local_dir), so a deploy from main ships the new allow-list.run_tool_job) already has a 30-minute budget and the same image.svar_forecastas "cannot be run as a job".nowcast.pyturns that into a plain "redeploy first" message.Workflow comment in
nowcast-round.ymlupdated. No behaviour changes there.This needs a deploy to work. Merging touches
integration/**, so Deploy MCP server to Modal runs on merge. Itsmodal deploystep publishes the new allow-list even though its smoke-test step is red (see the companion PR for the smoke tests). The live job path cannot be exercised before merge without a manual deploy, so it is untested live. The client logic is unit-tested against a scripted server.Tests
forecasts/tests/test_nowcast_job.py(13 tests). Ten driverun_as_jobagainst a scripted server:forecast_ukdirectly;svar_forecasttoJOB_TOOLSand to whatforecast_ukcalls.Three more run
fetch_forecast's real call path with the MCP client replaced by fakes that hold live anyio task groups, as the real client does. The first commit raisedHostedToolErrorinside those contexts, so anExceptionGroupwrapped it and the error was retried as a transport failure: "Redeploy" never printed and a failed job was polled again. The second commit (f08fb7d5) judges the reply after the contexts close. Against the first commit, 2 of these 3 tests fail; on this branch all 3 pass. They are skipped whereanyiois not installed (the plain-python CI gates).Results:
run_as_jobdoes not exist.forecasts/testspasses in full (13/13 for the new file, run with anyio installed).integration/tests/test_jobs.py,test_drift_check.pyandtest_tool_surface.py: 89 passed.After merge
Wait for the deploy step to finish (not the smoke test), then run Actions → Archive a forecast round before release → Run workflow on main with the defaults. The round does not depend on #195:
data/latestalready announcesuk_gdp_cvmfor 12 Nov.There is no
DATA_PR_TOKENsecret yet (#223). The round is pushed toforecasts/nowcast-roundbefore the PR step, so if that step fails, open the PR from the compare link it prints.🤖 Generated with Claude Code