Skip to content

feat!: share one jittered retry middleware across Auth, PostgREST, Storage and Functions - #1341

Draft
grdsdev wants to merge 1 commit into
mainfrom
guilhermesouza/sdk-1791-unify-retry-policy-jittered-backoff-retry-after-one
Draft

grdsdev wants to merge 1 commit into
mainfrom
guilhermesouza/sdk-1791-unify-retry-policy-jittered-backoff-retry-after-one

Conversation

@grdsdev

@grdsdev grdsdev commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Auth, PostgREST, Storage and Functions now retry through a single middleware driven by a RetryPolicy value: full-jitter capped exponential backoff, Retry-After honoured up to the cap, idempotent methods only unless an Idempotency-Key header is present, and an immediate stop on cancellation. Every retry carries X-Retry-Count: n.

The retry rule is per target. PostgREST keeps its fixed postgrest-js rule (GET/HEAD, 503/520, 4 attempts) and only its on/off switch stays public; its private loop is deleted. Storage and Functions gain retries for the first time, with a public, configurable retryPolicy. Auth keeps retrying POST so token refreshes are replayed. The Realtime reconnect delay carries the same full jitter. Only URLError counts as a transport failure; errors thrown by user code propagate untouched.

Breaking (behavior only, compiles silently): retry timing changes for every module, Auth makes 3 attempts instead of 2, and Storage/Functions start retrying by default. See the new section in V3_MIGRATION.md.

Review first: Sources/Helpers/HTTP/RetryPolicy.swift (the delay math and Retry-After parsing) and Sources/Helpers/HTTP/RetryRequestInterceptor.swift (what is retried). Everything else is wiring.

Test evidence

━ Test run with 1503 tests in 148 suites passed after 5.347 seconds with 1 known issue.
CSpell: Files checked: 402, Issues found: 0 in 0 files.
./scripts/test-docs.sh  → exit 0, no DocC warnings
./scripts/format.sh     → working tree clean

The known issue is pre-existing. New tests: RetryPolicyTests (jitter bounds, cap, Retry-After delta-seconds / HTTP-date / garbage), a rewritten RetryRequestInterceptorTests (statuses, methods, idempotency key, attempts, cancellation, bodies, delays, X-Retry-Count), Storage and Functions retry tests, and a PostgREST test pinning that a 500 on GET is never retried.

Companion spec drafts for database.configuration.auto_retry and storage.configuration.auto_retry are written locally in supabase/sdk and will follow as a separate PR.

Fixes SDK-1791

…orage and Functions

Auth, PostgREST, Storage and Functions now retry through a single
middleware driven by a `RetryPolicy` value: full-jitter capped exponential
backoff, `Retry-After` honoured up to the cap, idempotent methods only
unless an `Idempotency-Key` header is present, stop on cancellation.
The retry rule is per target. PostgREST keeps its fixed postgrest-js rule
(GET/HEAD, 503/520, 4 attempts) and only its on/off switch is public; its
private loop is deleted. Storage and Functions gain retries for the first
time, with a public, configurable `retryPolicy`. Auth keeps retrying POST
so token refreshes are replayed. The Realtime reconnect delay carries the
same full jitter.

BREAKING CHANGE: retry timing changes for every module (jitter instead of
a fixed schedule; Auth makes 3 attempts instead of 2), Storage and
Functions start retrying transient failures by default, and only
`URLError` counts as a retryable transport failure. See V3_MIGRATION.md.

Fixes SDK-1791

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

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.

@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 34894874449

Warning

No base build found for commit db9ae1f on main.
Coverage changes can't be calculated without a base build.
If a base build is processing, this comment will update automatically when it completes.

Coverage: 88.099%

Details

  • Patch coverage: 1 uncovered change across 1 file (157 of 158 lines covered, 99.37%).

Uncovered Changes

File Changed Covered %
Sources/Helpers/HTTP/RetryRequestInterceptor.swift 45 44 97.78%
Total (10 files) 158 157 99.37%

Coverage Regressions

Requires a base build to compare against. How to fix this →


Coverage Stats

Coverage Status
Relevant Lines: 11739
Covered Lines: 10342
Line Coverage: 88.1%
Coverage Strength: 53.14 hits per line

💛 - Coveralls

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