Skip to content

feat: Introduce step() method and timeout functionality - #9

Merged
alexmarqs merged 4 commits into
mainfrom
feat/add-steps
Jun 21, 2026
Merged

alexmarqs merged 4 commits into
mainfrom
feat/add-steps

Conversation

@alexmarqs

@alexmarqs alexmarqs commented Jun 20, 2026 •

Copy link
Copy Markdown
Owner
  • Added step(description, run, rollback, options?) to streamline the process of running an action and registering its rollback in one call.
  • Implemented timeout options for both individual steps and the overall operation, throwing a TimeoutError if the action does not settle in time.
  • Updated documentation and tests to reflect these new features, ensuring clarity on usage and behavior during timeouts.

Summary by CodeRabbit

Release Notes

  • New Features

    • New step() method for atomic pairing of forward actions with rollback compensation in a single call.
    • Timeout support at both per-step and per-operation levels with AbortSignal for cancellation.
    • New TimeoutError exception class for timeout scenarios; rollback still executes on timeout.
  • Documentation

    • Updated guides with timeout and cancellation usage examples.

- Added `step(description, run, rollback, options?)` to streamline the process of running an action and registering its rollback in one call.
- Implemented timeout options for both individual steps and the overall operation, throwing a `TimeoutError` if the action does not settle in time.
- Updated documentation and tests to reflect these new features, ensuring clarity on usage and behavior during timeouts.
@changeset-bot

changeset-bot Bot commented Jun 20, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1f2b7fb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
rollbackit Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jun 20, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@alexmarqs, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 44 minutes and 33 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3850d44f-1c53-450a-baaf-e3967ce88839

📥 Commits

Reviewing files that changed from the base of the PR and between 1938483 and 1f2b7fb.

📒 Files selected for processing (2)
  • CLAUDE.md
  • README.md
📝 Walkthrough

Walkthrough

Adds a step(description, run, rollback, options?) method to Rollback that runs a forward action and conditionally registers its compensation only on success. Introduces TimeoutError extends RollbackError, a runWithTimeout helper using Promise.race and AbortController, per-step StepOptions.timeout, whole-operation WithRollbackOptions.timeout, and AbortSignal forwarding into withRollback's callback.

Changes

step API, TimeoutError, and AbortSignal integration

Layer / File(s) Summary
Public type contracts
src/types.ts, src/index.ts
Adds StepOptions (extends RollbackOperationOptions with timeout?), adds step<T> method to Rollback, extends WithRollbackOptions with timeout?, and re-exports TimeoutError and StepOptions from the package entry point.
TimeoutError and runWithTimeout helper
src/lib/errors.ts, src/lib/operations.ts
Defines TimeoutError extends RollbackError with a timeout-ms message. Adds runWithTimeout that creates an AbortController and races execution against a deadline timer, aborting and rejecting with TimeoutError on expiry. Adds shared throwIfAlreadyRolledBack guard.
step method and withRollback timeout wiring
src/lib/operations.ts, src/lib/helpers.ts
add uses the shared guard; step runs the forward action via runWithTimeout, performs pre- and post-run rolled-back checks, then registers the compensation closure. withRollback wraps fn(rollback, signal) with runWithTimeout and updates the fn signature to accept AbortSignal.
Tests: createRollback.step and withRollback timeouts
tests/index.test.ts
Adds describe("createRollback.step") covering result propagation, deferred undo registration, LIFO unwinding, no undo on throw, and timeout/abort edge cases. Extends withRollback tests with outer timeout rollback, abort-signal firing, inline step timeout unwinding, onFailures observation, and in-flight step post-timeout guard.
Documentation
README.md, CLAUDE.md, .changeset/curvy-steps-cancel.md
README gains step() and timeout feature descriptions, quick-start rewrite, API table additions (step, StepOptions.timeout, WithRollbackOptions.timeout), and FAQ revisions. CLAUDE.md expands invariants, step/timeout guard ordering, and error subclass list. Changeset records the minor release.

Sequence Diagram(s)

sequenceDiagram
  actor Caller
  participant withRollback
  participant runWithTimeout
  participant AbortController
  participant Rollback
  participant step

  Caller->>withRollback: withRollback(fn, { timeout: N })
  withRollback->>Rollback: createRollback()
  withRollback->>runWithTimeout: runWithTimeout(fn, N)
  runWithTimeout->>AbortController: new AbortController()
  runWithTimeout->>step: fn(rollback, signal)

  alt forward action resolves in time
    step->>runWithTimeout: result
    runWithTimeout->>withRollback: result
    withRollback->>Rollback: commit()
    withRollback-->>Caller: return result
  else step-level timeout fires
    runWithTimeout->>AbortController: abort()
    runWithTimeout-->>step: TimeoutError
    step->>Rollback: throwIfAlreadyRolledBack (post-run guard)
    step-->>withRollback: TimeoutError propagates
    withRollback->>Rollback: rollback() → unwind LIFO
    withRollback-->>Caller: throw TimeoutError
  else outer withRollback timeout fires
    runWithTimeout->>AbortController: abort()
    runWithTimeout-->>withRollback: TimeoutError
    withRollback->>Rollback: rollback() → unwind LIFO
    withRollback-->>Caller: throw TimeoutError
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 Hop forward, then pause — did it land?
Only then do I stash the undo at hand.
A clock ticks away, AbortSignal fires,
TimeoutError leaps over the wires.
LIFO unwinds, the warren stays neat —
no step left dangling, rollback complete! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely captures the two main changes: introducing a step() method and timeout functionality.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/add-steps

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLAUDE.md`:
- Line 32: Update the post-rollback invariant description for the rollback()
method to specify that both add() and step() throw RolledBackError after the
instance is rolled back, rather than only mentioning add(). The current text on
line 32 states "After that, add() throws RolledBackError" but should be expanded
to indicate that step() also throws RolledBackError in the same scenario to
accurately reflect the engine contract for both methods.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 983705f1-55b5-4e48-9d9c-ad748da145b2

📥 Commits

Reviewing files that changed from the base of the PR and between b5331b4 and 1938483.

📒 Files selected for processing (9)
  • .changeset/curvy-steps-cancel.md
  • CLAUDE.md
  • README.md
  • src/index.ts
  • src/lib/errors.ts
  • src/lib/helpers.ts
  • src/lib/operations.ts
  • src/types.ts
  • tests/index.test.ts

Comment thread CLAUDE.md Outdated
- Clarified the behavior of the `step(description, run, rollback, options?)` method, emphasizing the return values and error propagation.
- Simplified explanations regarding the use of timeouts in both individual steps and overall operations.
- Enhanced documentation on handling `AbortSignal` and the implications of timeouts on resource creation and rollback registration.
- Updated the documentation for the `rollback()` method to specify that both `add()` and `step()` throw `RolledBackError` after a rollback, enhancing clarity on error handling.
- Emphasized the safety of repeat `rollback()`/`commit()` calls as no-ops, while noting that registration after a rollback will throw an error.
- Updated the section on timeouts to clarify the implications of a step hanging and the importance of setting deadlines that precede platform timeouts.
- Enhanced the language to improve readability and understanding of resource management during rollback scenarios.
@alexmarqs
alexmarqs merged commit eadbec2 into main Jun 21, 2026
5 checks passed
@alexmarqs
alexmarqs deleted the feat/add-steps branch June 21, 2026 16:57
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.

1 participant