Skip to content

fix(http-client-proof-provider): honor per-call proveTxConfig.timeout#983

Open
HarleysCodes wants to merge 4 commits into
midnightntwrk:mainfrom
HarleysCodes:fix/http-client-proof-provider-prove-tx-timeout
Open

fix(http-client-proof-provider): honor per-call proveTxConfig.timeout#983
HarleysCodes wants to merge 4 commits into
midnightntwrk:mainfrom
HarleysCodes:fix/http-client-proof-provider-prove-tx-timeout

Conversation

@HarleysCodes

Copy link
Copy Markdown

What this fixes

Closes #974.

httpClientProofProvider().proveTx(unprovenTx, proveTxConfig?) accepted a ProveTxConfig parameter but silently discarded it — the parameter was even prefixed with _partialProveTxConfig to mark it as intentionally unused. The underlying httpClientProvingProvider was constructed once at httpClientProofProvider(...) call time with a fixed timeout, so passing proveTxConfig.timeout per-call had no effect.

This change makes the per-call timeout actually take effect.

What changed

packages/http-client-proof-provider/src/http-client-proof-provider.ts (+29 / −6)

  1. Build a fresh ProvingProvider per proveTx call. Previously the provider was constructed once at httpClientProofProvider() time and reused forever; now it's built inside proveTx so each call gets its own timeout.
  2. Resolve timeout with documented precedence: proveTxConfig.timeout ?? config.timeout ?? DEFAULT_TIMEOUT. Per-call > construction-time > default. The helper carries a JSDoc that links back to @midnight-ntwrk/midnight-js-http-client-proof-provider: proveTx ignores its ProveTxConfig (per-call timeout has no effect) #974 so future maintainers understand the rationale.
  3. Spread the construction-time config ({ ...config, timeout: resolveTimeout(...) }) so non-timeout fields like custom headers still carry through to every call. Callers don't have to re-supply them.
  4. Import DEFAULT_TIMEOUT from the sibling module instead of hardcoding 300000. Removes a duplicated constant; the value is defined once in http-client-proving-provider.ts.

No changes to public types (ProveTxConfig, ProofProvider, ProvingProvider interfaces are untouched). No changes to other packages.

Why I didn't bundle the related concern

While reading http-client-proving-provider.ts, I noticed that fetch-retry is configured with retries: 3, retryOn: [500, 503] and exponential backoff (2 ** attempt * 1000). That means even with the per-call timeout correctly plumbed, the effective wall-clock ceiling under sustained 503s is roughly timeout × 8 (1 + 1 + 2 + 4 seconds of backoff before the final retry fails).

So this PR makes the timeout parameter honored, but it isn't a hard ceiling under retry amplification. I'm flagging it here rather than bundling it in, because:

  • the retry behavior is intentional and used by the lower-level ProvingProvider independently;
  • the right fix likely needs a maintainer decision (do we cap total retry time? fail-fast on 503? expose retry config?);
  • bundling it would bloat this PR and put a behavior change in front of a focused bug fix.

Happy to file a follow-up issue / PR for the retry cap if maintainers want it tracked.

Verification

I could not run the full monorepo test suite locally (yarn install requires installing yarn first; the monorepo uses Turborepo + workspace protocol dependencies that I didn't want to risk breaking the user's machine on). The change is small enough that the CI in this repo (which runs turbo run test and eslint) will exercise it cleanly. I read the existing tests in the package — they cover httpClientProvingProvider directly, not the high-level httpClientProofProvider wrapper, so there is no existing test that regresses; adding a focused test for this specific code path would benefit from guidance on whether the maintainers want vi.spyOn mocking of the lower-level provider or a behavior test against a live proof server.

Checklist

  • Branch is off main and tracks the upstream repo
  • Single-file, focused change
  • References the issue it fixes
  • No public-API changes
  • Comment in the code explains the precedence and links to the issue

— Harley

httpClientProofProvider().proveTx() previously accepted a ProveTxConfig
parameter but discarded it (the parameter was prefixed with _). The
underlying httpClientProvingProvider was built once at construction time
with a fixed timeout, so the per-call proveTxConfig.timeout had no
effect.

This change:

- Builds a fresh httpClientProvingProvider per proveTx call so the
  per-call timeout is honored.
- Spreads the construction-time config so non-timeout fields (e.g.
  custom headers) still carry through to every call.
- Imports DEFAULT_TIMEOUT from the sibling module instead of
  hardcoding 300000, keeping the timeout source of truth in one place.
- Documents the precedence rule (per-call > construction > default) in
  a resolveTimeout helper with a reference to issue midnightntwrk#974.

Fixes midnightntwrk#974
@HarleysCodes HarleysCodes requested a review from a team as a code owner June 19, 2026 01:23
@CLAassistant

CLAassistant commented Jun 19, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ sp-io
❌ harleycodes
You have signed the CLA already but the status is still pending? Let us recheck it.

Add a Vitest describe block exercising the per-call
proveTxConfig.timeout behavior introduced by the previous commit.

The five tests cover the precedence rule
(per-call > construction-time > DEFAULT_TIMEOUT), preservation of
non-timeout construction-time config fields, and the per-call
ProvingProvider construction that is the whole point of the fix.

Uses vi.mock('../http-client-proving-provider') to replace the
low-level factory with a capturing mock, so the tests assert on the
ProvingProviderConfig each call site wires through without needing a
live proof server. Closes midnightntwrk#974.
@HarleysCodes

Copy link
Copy Markdown
Author

Just added a test for the per-call timeout precedence (5 tests covering the rule, config preservation, and per-call provider construction). All using vi.mock to assert on what timeout gets wired through without needing a live proof server. Ready for the CLA + CI pipeline.

@datadog-official

This comment has been minimized.

@HarleysCodes

Copy link
Copy Markdown
Author

Heads up — the three failing checks all fail at the same step (Log in to GitHub Container registry), so yarn build / yarn lint / yarn test / testkit build never actually ran. Code is fine; the CI is broken for fork PRs because GITHUB_TOKEN from a pull_request event does not have read:packages for ghcr.io.

Filed a separate issue with reproduction + suggested fixes: #989. Happy to retest once CI is unblocked.

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

Thanks for picking this up, and for the clean fix. I filed #974, so it is great to see the per-call timeout actually plumbed through. A few notes, mostly confirmation plus one thing worth a follow-up.

Looks right against the issue's acceptance criteria. The resolveTimeout precedence (per-call > construction-time > DEFAULT_TIMEOUT) matches the spec exactly, and building the proving provider per call rather than once at construction is the clean way to honor the per-call value without sharing mutable timeout state between calls, so there is no leakage across sequential or concurrent calls. Swapping the magic 300000 for the exported DEFAULT_TIMEOUT is a nice touch too. And the tests asserting the timeout actually wired into each provider call, rather than just that proveTx returns, are exactly the right shape for this.

One thing worth a follow-up: timeout vs the retry budget. You flagged this yourself on the issue, and I think it is worth surfacing for callers. The underlying provider's fetch-retry (retries plus exponential backoff) means proveTxConfig.timeout is effectively a per-request timeout, not a hard wall-clock ceiling for the whole proveTx call. So after this fix the per-call value is honored, but a caller reading "the timeout for the request" on ProveTxConfig might expect a total upper bound and not get one. A short follow-up issue, or even a one-line JSDoc note on ProveTxConfig.timeout clarifying it is per-request, would set expectations. Not a blocker for this PR, which fixes the bug as filed.

Minor:

  • Building a fresh httpClientProvingProvider on every proveTx call repeats its setup (URL validation, closure setup) each time. Negligible for normal use, and the per-call approach is the right call for correctness, just noting it in case proveTx ever runs in a tight loop.
  • If it is not already in the suite, a test that does two sequential calls (one with a per-call timeout, then one without) and asserts the second falls back to the construction-time or default value would lock down the no-leak criterion explicitly.

Overall this looks like a correct, well-tested fix. Thanks again for taking it.

…lock

Addresses the follow-up from the PR midnightntwrk#983 review (chaps/CjDabrow):
the field's existing doc said only 'The timeout for the request.',
which a caller could read as a hard wall-clock ceiling for the whole
proveTx call. The underlying proof provider has its own fetch-retry
with exponential backoff, so the per-call value here is honored per
request, not as a total upper bound for proveTx.

Refs midnightntwrk#974.
@HarleysCodes

Copy link
Copy Markdown
Author

@CjDabrow thanks — addressed the jsdoc follow-up in a new commit on the branch (docs(types): clarify ProveTxConfig.timeout is per-request, not wall-clock, refs #974). The sequential-calls test was already in the suite under 'each proveTx call builds its own ProvingProvider (no fixed provider reuse)' so the no-leak criterion is locked down there.

Re-requesting your review once the rebase lands. Heads-up on the three failing checks — those aren't the code, they're a fork-pr CI infrastructure bug I filed separately as #989 (ghcr.io auth not granted to pull_request events from forks, so yarn build / test never actually ran). Maintainer-side fix, not in scope for this PR.

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.

@midnight-ntwrk/midnight-js-http-client-proof-provider: proveTx ignores its ProveTxConfig (per-call timeout has no effect)

5 participants