-
Notifications
You must be signed in to change notification settings - Fork 20
fix: retry improvements #198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThe retry logic for HTTP requests was refactored to centralize and streamline the delay mechanism using asynchronous scheduling, eliminating the creation of new HttpClient instances for each retry. The handling of the "Retry-After" header was simplified, and related tests were updated to use shorter delays and verify the precedence of "Retry-After" over minimum retry delays. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant HttpRequestAttempt
participant HttpClient
participant Timer
Client->>HttpRequestAttempt: sendRequest()
HttpRequestAttempt->>HttpClient: send()
alt Success
HttpClient-->>HttpRequestAttempt: response
HttpRequestAttempt-->>Client: response
else Network/HTTP Error & shouldRetry
HttpRequestAttempt->>Timer: delayedRetry(delay)
Timer-->>HttpRequestAttempt: (after delay)
HttpRequestAttempt->>HttpClient: send() (retry)
loop Until success or max retries
HttpClient-->>HttpRequestAttempt: response/error
alt Success
HttpRequestAttempt-->>Client: response
else Retryable error
HttpRequestAttempt->>Timer: delayedRetry(next delay)
end
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~18 minutes Possibly related PRs
Suggested reviewers
✨ Finishing Touches🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Codecov Report✅ All modified and coverable lines are covered by tests. ❌ Your project status has failed because the head coverage (34.58%) is below the target coverage (80.00%). You can increase the head coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #198 +/- ##
=========================================
Coverage 34.57% 34.58%
- Complexity 1042 1043 +1
=========================================
Files 185 185
Lines 6984 6980 -4
Branches 790 790
=========================================
- Hits 2415 2414 -1
+ Misses 4464 4463 -1
+ Partials 105 103 -2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/test/java/dev/openfga/sdk/api/client/HttpRequestAttemptRetryTest.java (1)
322-359
: Repeated real-time back-off assertionsSame flakiness risk across several new tests. Consider consolidating into one timing-sensitive test or mocking
ExponentialBackoff
to return deterministic values.Also applies to: 361-400, 624-630, 670-671, 747-749
🧹 Nitpick comments (3)
src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java (2)
107-116
: Telemetry parity missing for HTTP-error retries
handleNetworkError
adds thehttp.request.resend_count
attribute, buthandleHttpErrorRetry
no longer does. For consistency in dashboards, add the same attribute there.
131-152
: Potential overflow & thread utilisation indelayedRetry
retryDelay.toNanos()
will overflow for durations ≥ ~292 years or throwArithmeticException
; safer to pass milliseconds.CompletableFuture.runAsync(…)
spins a task per retry. With highmaxRetries
this is fine, but if called thousands of times (e.g., bulk operations) consider re-using a scheduler (ScheduledExecutorService
) to avoid excess threads inForkJoinPool
.- CompletableFuture.delayedExecutor(retryDelay.toNanos(), TimeUnit.NANOSECONDS)) + CompletableFuture.delayedExecutor(retryDelay.toMillis(), TimeUnit.MILLISECONDS))src/test/java/dev/openfga/sdk/api/client/HttpRequestAttemptRetryTest.java (1)
247-284
: Wall-clock timing assertions may be flakyTests assert on elapsed milliseconds (
>8 ms
,<400 ms
, etc.). On loaded CI runners or different JVMs these can intermittently fail. Prefer:• Using a virtual clock /
Clock
injection; or
• Asserting only order (retry happened) and inspecting captured delays via mock/scheduler.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java
(5 hunks)src/main/java/dev/openfga/sdk/util/RetryStrategy.java
(1 hunks)src/test/java/dev/openfga/sdk/api/client/HttpRequestAttemptRetryTest.java
(21 hunks)src/test/java/dev/openfga/sdk/util/RetryStrategyTest.java
(2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Test and Build OpenFGA (11)
- GitHub Check: Test and Build OpenFGA (21)
- GitHub Check: Test and Build OpenFGA (17)
- GitHub Check: Analyze (java)
🔇 Additional comments (3)
src/test/java/dev/openfga/sdk/util/RetryStrategyTest.java (1)
38-49
: Rename and assertion update look correctTest now validates that a smaller
Retry-After
value (50 ms) is used verbatim—exactly what the new strategy requires. Nothing further.src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java (1)
83-88
: Helper method improves clarityUsing
getHttpClient()
isolates the caching concern—nice.src/test/java/dev/openfga/sdk/api/client/HttpRequestAttemptRetryTest.java (1)
70-71
: FractionalRetry-After
header is non-standardRFC 9110 allows only integer seconds or HTTP-date. Using
"0.05"
works with our parser but is not interoperable. Recommend switching to"0"
(allowed) and configuringminimumRetryDelay
/jitter in code instead, or treat header milliseconds via custom header for tests.Also applies to: 105-106, 167-168
fix: Improved Retry Handling and Retry-After Header Support
Overview
This PR makes two key improvements to the retry handling implementation:
HttpClient
s per retry withCompletableFuture.supplyAsync()
timing andHttpClient
reuseRetry-After
headers now take precedence over client minimum retry delaysKey Improvements
1. Efficient Retry Timing with
HttpClient
ReuseFile:
src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java
Problems with Current Approach
The current approach ccreates a new HttpClient with a delayed executor for each retry:
Issues with this approach:
Improved Implementation
Benefits of this approach:
HttpClient
instead of creating new instancesCompletableFuture
chaindelayedExecutor()
for nanosecond-precision delays2. Retry-After Header Precedence
File:
src/main/java/dev/openfga/sdk/util/RetryStrategy.java
Key behavioral change: Server-specified
Retry-After
headers now take precedence over client minimum retry delays.Why this matters:
Technical Benefits
Performance
Reliability
Maintainability
delayedRetry()
methodTesting
Test Suite Optimization
File:
src/test/java/dev/openfga/sdk/api/client/HttpRequestAttemptRetryTest.java
Performance Improvement
🧪 Testing
Test Results
Test Categories Covered
📋 Validation Criteria
This PR satisfies the following validation criteria:
🔗 References
[2^loopCount * 100ms, 2^(loopCount + 1) * 100ms]
🎯 Impact
This PR ensures that the Java SDK's retry logic:
The changes are backward compatible and improve both code quality and specification compliance.
Summary by CodeRabbit
Refactor
Bug Fixes
Tests