Skip to content

Reject nested steps and missing cursor targets - #1534

Merged
bgentry merged 2 commits into
masterfrom
bg/reproduce-nested-resumable-steps
Oct 25, 2026
Merged

bgentry merged 2 commits into
masterfrom
bg/reproduce-nested-resumable-steps

Conversation

@bgentry

@bgentry bgentry commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Nested resumable steps can save unreachable resume points or replay rolled-back parent checkpoints. Reject nesting before invoking a child callback in Go, JavaScript, and Rust, matching Java and Ruby, and keep a nesting failure from completing the parent or clearing its cursor.

A retry can also silently complete when it omits a saved cursor-only step. Track those targets independently of the existing skip boundary in all five runtimes. Require the cursor API when reaching a target, preserve the original checkpoint while targets remain unmatched, and reject transactional checkpoint writes that would advance past them. Restoring an omitted step can then recover and checkpoint normally.

The metadata format stays unchanged. Jobs with an existing step marker keep their behavior, including legacy stale cursor entries. Shared fixtures and database regressions cover compatibility and recovery, and release notes explicitly call out the nesting restriction.

@bgentry
bgentry force-pushed the bg/fix-resumable-progress branch from e55befb to 88abef3 Compare October 24, 2026 20:23
@bgentry
bgentry force-pushed the bg/reproduce-nested-resumable-steps branch from 24e18d3 to a79aaa9 Compare October 24, 2026 20:24
@bgentry
bgentry force-pushed the bg/fix-resumable-progress branch from 88abef3 to f45a4df Compare October 24, 2026 20:33
@bgentry
bgentry force-pushed the bg/reproduce-nested-resumable-steps branch from a79aaa9 to a379437 Compare October 24, 2026 20:33
Base automatically changed from bg/fix-resumable-progress to master October 24, 2026 20:42
@brandur

brandur commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-24T21:20:16.799989Z a379437 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a379437228

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/riverplugin/plugin.go
@bgentry

bgentry commented Oct 24, 2026

Copy link
Copy Markdown
Contributor Author

@brandur PR copy was bad here, but this is not actually mergeable. There are some key design issues with allowing nested resumable jobs. So far this PR mainly illustrates their failure with test cases.

What do you think about just blocking them? Is there even a use case for it?

@brandur

brandur commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

@bgentry The only thing that's coming to mind is if you had kind of a messy codebase happening and there was a variety of checkpoints across job implementation / controller / model helpers, then it might be easier for you to refactor code if we just allowed nesting and and approximately the right thing would happen.

Especially if it doesn't work though, I'm good with banning it. It didn't occur to me as something that people would even try to do when I wrote the first implementation.

Nested resumable steps can persist unreachable resume points and replay
rolled-back parent checkpoints when a child updates its cursor.

Reject starting a step while another step callback is active in Go,
JavaScript, and Rust, matching Java and Ruby. Preserve nesting errors so
an unsuccessful parent cannot be marked complete or lose its cursor.
Remove the enclosing-step state that nesting requires, and document the
restriction in the public APIs and guides.

Replace the draft reproductions with coverage for plain and cursor
nesting, committed and rolled-back parent checkpoints, and caught nesting
errors. Verify all parent and child step combinations across runtimes.
@bgentry
bgentry force-pushed the bg/reproduce-nested-resumable-steps branch from a379437 to 2ba8a0d Compare October 24, 2026 23:34
@bgentry bgentry changed the title demonstrate nested resumable failures reject nested resumable steps Oct 24, 2026
@bgentry bgentry changed the title reject nested resumable steps reject nested steps and missing cursor targets Oct 25, 2026
@bgentry bgentry changed the title reject nested steps and missing cursor targets Reject nested steps and missing cursor targets Oct 25, 2026
A first-step cursor can be saved without a completed-step checkpoint.
When a retry omits that step, the job can silently complete or persist a
later checkpoint that makes the original cursor unreachable.

Track cursor-only targets independently of the skip boundary across all
five runtimes. Require each target to be reached through a cursor step,
and preserve the original checkpoint while targets remain unmatched.
Reject transactional checkpoints that would advance past those targets.
Keep the existing metadata format and preserve behavior for jobs with a
step marker, including legacy stale cursor entries.

Add shared compatibility cases and database recovery coverage, including
zero and null cursors, renamed steps, plain-step replacements, earlier
failures, and checkpoints inside a restored target. Document the
cursor-only restriction and the behavior change for nested steps.
@bgentry
bgentry force-pushed the bg/reproduce-nested-resumable-steps branch from 1f3da46 to 9d94fc6 Compare October 25, 2026 01:16
@bgentry
bgentry marked this pull request as ready for review October 25, 2026 01:18
@bgentry

bgentry commented Oct 25, 2026

Copy link
Copy Markdown
Contributor Author

@brandur updated to reject nested steps and missing cursor targets

@bgentry
bgentry merged commit dc7dd6e into master Oct 25, 2026
68 checks passed
@bgentry
bgentry deleted the bg/reproduce-nested-resumable-steps branch October 25, 2026 01:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants