job_runs: wait for run completion, expose output, dedupe deploy retries - #5882
Open
radakam wants to merge 1 commit into
Open
job_runs: wait for run completion, expose output, dedupe deploy retries#5882radakam wants to merge 1 commit into
radakam wants to merge 1 commit into
Conversation
Collaborator
Integration test reportCommit: 2d11c4d
11 interesting tests: 4 RECOVERED, 3 FAIL, 3 SKIP, 1 KNOWN
|
radakam
force-pushed
the
job-runs-idempotency-wait-for-completion
branch
from
July 13, 2026 09:13
acf313b to
3a5ea16
Compare
radakam
force-pushed
the
job-runs-idempotency-wait-for-completion
branch
from
July 14, 2026 10:07
51dca78 to
66ca15a
Compare
radakam
marked this pull request as ready for review
July 14, 2026 11:52
Contributor
Approval status: pending
|
radakam
added a commit
that referenced
this pull request
Jul 28, 2026
## Changes The fake workspace reported every run as `TERMINATED SUCCESS`, overwriting the `FAILED` state it had just recorded for a task it executed locally. A run now reports the terminal state its tasks add up to. Tasks whose code the fake workspace does not have are left successful. An immutable deployment, for example, uploads the bundle as a snapshot zip that the fake workspace never unpacks, so there is nothing to execute; that gap is in the fake workspace, not in the job under test. With that, `job_runs/failed_run` drops the `runs/get` and `runs/get-output` stubs from its `test.toml` and fails for real, on a task that exits non-zero. ## Why Follow-up to #5882, where a stub stood in for a failing run because the fake workspace could not produce one. Splitting it out keeps the behaviour change for existing tests out of that PR. The stub could not know the test server's address, so it could not report a run page URL; the golden now covers the run URL and the progress lines too. ## Tests `libs/testserver` unit tests for the rollup, for completing the tasks that jobs/runs/submit leaves running, and for a task whose code is missing not failing its run. `job_runs/failed_run` covers the end-to-end path. The rest of the acceptance suite passes unchanged.
denik
reviewed
Jul 28, 2026
| resources.job_runs.my_run: Run URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?o=[NUMID] | ||
| resources.job_runs.my_run: [TIMESTAMP] "my-job" RUNNING | ||
| resources.job_runs.my_run: [TIMESTAMP] "my-job" TERMINATED FAILED task main failed | ||
| Error: cannot create resources.job_runs.my_run: job run [NUMID] did not succeed: FAILED: task main failed |
Contributor
There was a problem hiding this comment.
if possible, use replace_ids.py or add_repl.py to record replacements for specific IDs.
denik
reviewed
Jul 28, 2026
|
|
||
| STATE=.databricks/bundle/default/resources.json | ||
| run_id() { | ||
| jq -r '.state["resources.job_runs.my_run"].__id__' "$STATE" |
DoCreate derives idempotency_token as a SHA-256 of the run config plus a create identity (workspace root path, resource key, and the prior run id when re-creating a vanished run), so a deploy that fires run-now and then crashes before recording the id rejoins that same run on retry instead of starting a duplicate. The token is computed by the CLI and rejected if set in bundle configuration; the new bundle-only rerun_token field folds into it, so bumping it re-runs a configuration that already ran. DoDelete becomes a noop: the Jobs API keeps an idempotency_token reserved once the run it triggered is deleted, so deleting the run would tombstone the token and break re-running the same configuration.
radakam
force-pushed
the
job-runs-idempotency-wait-for-completion
branch
from
July 28, 2026 22:08
d2a1cc6 to
2d11c4d
Compare
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.
Changes
Milestone 2 of the
job_runsresource (direct engine only): make a triggered run idempotent across retries, and wait for it so other resources can use its outcome.DoCreatecomputesidempotency_tokenas a SHA-256 of the run config plus a create identity (workspace root path, resource key, and the prior run id when re-creating a vanished run). A deploy that fires run-now and then crashes before recording the id rejoins the same run on retry instead of starting a duplicate. The token is never user-settable; a newvalidate:job_runsmutator rejects it in bundle config.SUCCESScompletes the deploy; anything else fails it with the failed task, the message that task reported, and a link to the run page. Bounded by 24h, matchingbundle run. There is deliberately no config field to opt out:ignore_local_changeswould make it a silent no-op after the first deploy.DoCreatenow names the run it reused and points atrerun_token.rerun_tokenin tracked source.DoCreatenow folds such a run's id into the token, the same rotation already used for a vanished run, and re-issues run-now, which starts a fresh run. A run that this deploy started and that failed is still reported rather than silently retried. The walk is bounded at 10 attempts, since it costs one run-now per earlier consecutive failure.run_id,run_name,state,run_typeandrun_page_urlare readable by other resources, e.g.${resources.job_runs.nightly.state.result_state}.run_page_urlis normalized to the path form that resolves for non-admins.rerun_token. A bundle-only field folded into the token. Bump it to re-run a configuration that already ran successfully; retrying a run that did not succeed needs no change, since the next deploy starts a fresh one.DoDeleteis now a noop. A run is immutable history, and the Jobs API keeps anidempotency_tokenreserved after its run is deleted, so deleting would tombstone the token and break re-runs. Destroy and recreate leave the run in place.Supporting changes
dresources.CreateIdentity, attached byDeploymentUnit.Create, for resources deriving a stable create-time key.runPageURLmoved frombundle/runtolibs/workspaceurls.JobRunPageURL, now shared bybundle runandjob_runs.Tests
Unit tests for token derivation (stability, scoping, rotation), for each wait outcome (success, failed, skipped, internal error, abandoned wait, polling), and for each create path against a fake that models run-now dedupe: starting a fresh run, resuming a run still going, reusing a run that succeeded, rotating off a run that failed, reporting a run it started itself that failed, and the bound on the rotation walk.
Acceptance tests:
basic,redeploy,job_parameters,rerun,idempotent_recreate(retry mid-run with and without a recorded id),recreate_gone(run deleted out of band),token_survives_delete(flip-back reuses the original run and says so),distinct_runs(identical config under two keys),wait_output(downstream resource readsresult_state),failed_run(a failing run fails the deploy, then a redeploy rotates the token off it and starts a fresh run),validate.invariant/configs/job_run.yml.tmplis excluded from cloud runs: deploying it now waits for a real run, a real workspace reports a condition-task-only run asSKIPPED, and giving the job a task that succeeds would add a multi-minute cluster run to every variant in a suite that asserts plan and state invariants. Still covered locally.