Skip to content

fix: poll immediately and honor the timeout in SendUseroperationResponse.included - #209

Closed
Sednaoui wants to merge 2 commits into
devfrom
fix/130-polling-timeout
Closed

fix: poll immediately and honor the timeout in SendUseroperationResponse.included#209
Sednaoui wants to merge 2 commits into
devfrom
fix/130-polling-timeout

Conversation

@Sednaoui

@Sednaoui Sednaoui commented Jun 11, 2026

Copy link
Copy Markdown
Member

Fixes #130

Red/green verified with real timers (test/transport/includedPolling.test.js, mock transport): on pre-fix dev, an immediately-available receipt still took the full 3s interval and included(2, 2) threw after ~4s; with the fix the receipt returns in ~3ms and the timeout throws at ~2s.

Follow-up: non-finite timeoutInSeconds/requestIntervalInSeconds (e.g. NaN from Number(unsetEnvVar)) slipped past the <= 0 checks and, with the deadline loop, degraded into a ~1ms setTimeout polling indefinitely (measured: 258 polls in 300ms, never settling). included() now rejects non-finite inputs with a RangeError up front; covered by a regression test.

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Fixed polling behavior to check for results immediately, then wait between attempts instead of delaying the initial lookup.
    • Fixed timeout handling to prevent exceeding the specified maximum duration.
    • Added validation to reject invalid timeout and polling interval values upfront, preventing unintended high-frequency polling.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ef8b9f14-c0b6-4c89-8707-b106946f9178

📥 Commits

Reviewing files that changed from the base of the PR and between 3bd1466 and 0639fba.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • src/account/SendUseroperationResponse.ts
  • test/transport/includedPolling.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/transport/includedPolling.test.js

📝 Walkthrough

Walkthrough

SendUseroperationResponse.included() is refactored to use a deadline-based loop that polls immediately, caps each sleep to remaining time, and validates timing inputs for non-finite values. Tests and CHANGELOG.md updated to reflect and verify the behavior.

Changes

Polling Timeout Fix

Layer / File(s) Summary
Input validation and JSDoc updates
src/account/SendUseroperationResponse.ts
Reject non-finite/<=0 timeoutInSeconds and requestIntervalInSeconds; update JSDoc @throws text.
Deadline-based polling loop
src/account/SendUseroperationResponse.ts
Replace counter-based polling with a deadline-driven loop: poll immediately, compute remainingMs each iteration, cap sleep with Math.min(intervalMs, remainingMs), and throw AbstractionKitError { code: "TIMEOUT" } on expiry.
Polling behavior and validation tests
test/transport/includedPolling.test.js
Add mocked-transport tests confirming immediate resolution when receipt present, timeout rejection without full-interval overshoot, success when receipt appears later, and RangeError for non-finite timing inputs.
Changelog entry
CHANGELOG.md
Document corrected polling flow and upfront rejection of non-finite timing inputs in the [UNRELEASED] Bug Fixes section.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • sherifahmed990

Poem

🐰 I hopped through loops both wide and tight,
Polling at dawn, then again at night.
Now I check first, then nap between,
Timeout's capped — the timing's keen.
Cheers to code that hops just right!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description provides a clear summary of changes with verification details, but does not follow the repository's template structure with Summary, Test, and Risk/Compatibility sections. Consider restructuring the description to match the template format with dedicated Summary, Test, and Risk/Compatibility sections for consistency.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: fixing polling to start immediately and properly honor the timeout in SendUseroperationResponse.included().
Linked Issues check ✅ Passed The implementation fully addresses issue #130 by polling immediately, using a deadline-based loop to honor timeouts precisely, and rejecting non-finite inputs with validation.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the polling timeout issue and adding validation for non-finite inputs as specified in issue #130, with no extraneous modifications.

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


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

@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: 3bd146646f

ℹ️ 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".

if (remainingMs <= 0) {
break;
}
await this.delay(Math.min(requestIntervalInSeconds * 1000, remainingMs));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate finite polling inputs

When timeoutInSeconds or requestIntervalInSeconds is NaN (for example from Number(process.env.USEROP_TIMEOUT) with an unset variable), the existing <= 0 and < checks do not reject it, and this new capped-sleep path passes NaN to setTimeout. In Node that becomes a 1 ms timer; with a NaN timeout, remainingMs <= 0 is never true, so included() can poll indefinitely at high frequency, and with a NaN interval it floods until the timeout. Please reject non-finite values before entering the loop.

Useful? React with 👍 / 👎.

@sherifahmed990 sherifahmed990 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

included is usually used after sendUserOperation, so polling immediately is a guaranteed miss. It is better to wait first then poll to give a chance for the bundler to submit the bundle transaction.

@Sednaoui Sednaoui closed this Jun 13, 2026
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.

Fix: Polling timeout can overshoot by one full interval in SendUseroperationResponse

2 participants