Repository navigation
Commit 5c1467e
ref(transport): Measure rate-limit backoff on a monotonic clock (JAVA-574) (#6030)
* ref(transport): Measure rate-limit backoff on a monotonic clock (JAVA-574)
Retry-after limits were java.util.Date values derived from
System.currentTimeMillis(). A wall clock is the wrong instrument for a
backoff window: it steps when the device syncs time, so an NTP
correction could lift a 60 second rate limit early or extend it by
however far the clock jumped. The limits now live on the monotonic
clock, which counts forward at a steady rate and keeps counting while
the device sleeps, which is what a server-dictated wait means.
Storing Deadline rather than a timestamp also removes the duplicated
parameter on applyRetryAfterOnlyIfLonger, which took both an absolute
deadline and the delay needed to reach it, and lets three JdkObsolete
and JavaUtilDate suppressions go with the Dates.
RateLimiter also took the whole SentryOptions while reading exactly
three methods from it. It now depends on RateLimiterConfig, declared
next to its consumer, so what a rate limiter touches is three lines to
read rather than three hundred. SentryOptions implements it with no new
methods, so every existing caller compiles unchanged.
Both existing constructors stay, so the .api diff is additions only. The
ICurrentDateProvider one is deprecated and adapts the injected provider
rather than ignoring it, since a custom ITransportFactory may be passing
one.
One boundary moves by a nanosecond: a limit used to be active while
`now <= deadline` and is now active while `now < deadline`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Add changelog entries for JAVA-574
* ref(transport): Create RateLimiter through a factory (JAVA-574)
The RateLimiterConfig constructor is now private behind
RateLimiter.create, and both SentryOptions constructors are deprecated.
Handing over the whole options object hides which three of its methods a
rate limiter reads, which is the very thing the config interface exists
to name, so both transport factories call the factory method instead.
RateLimiterTest supplies its own RateLimiterConfig rather than a
SentryOptions carrying a @testonly executor setter and a reflective
client-report-recorder injection. A DeferredExecutorService replaces the
real executor, so the lifted-limit notification runs when the test says
so instead of a real second later, leaving the deadline's virtual clock
as the only clock in the test.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(transport): Tolerate a negative retry-after delay (JAVA-574)
A server-supplied `Retry-After: -1`, or a negative delay in
`X-Sentry-Rate-Limits`, reached `Deadline.after` unvalidated and threw
`IllegalArgumentException` out of response handling. Clamp a negative
amount to an already-passed deadline, restoring the behavior the
wall-clock implementation had, and keeping the tick arithmetic away from
wrapping on a large negative value.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* ref(transport): Keep RateLimiter(SentryOptions) as public API (JAVA-574)
RateLimiter is public because ITransport.getRateLimiter returns it and a
custom transport has to build one. Deprecating the options constructor
pointed those callers at RateLimiter.create, whose two parameter types
are both @ApiStatus.Internal, so following the deprecation meant reaching
into internal API.
Un-deprecate the options constructor and mark the factory internal
instead, which is what it already was in practice. Both transport
factories call the constructor, dropping the getMonotonicTicker/options
double-pass and, in the apache module, an internal call from another
module.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* ref(transport): Note why RateLimiter(SentryOptions) stays non-deprecated (JAVA-574)
Both transport factories go back to RateLimiter.create, which names the
collaborators a rate limiter reads instead of handing over the whole
options object. The constructor stays as the one path a caller outside
the SDK can take, and now says so: it is only non-deprecated because
create takes the internal MonotonicTicker, and should be deprecated once
that type is public API.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 663ad97 commit 5c1467e
10 files changed
Lines changed: 242 additions & 114 deletions
File tree
- sentry-apache-http-client-5/src/main/java/io/sentry/transport/apache
- sentry
- api
- src
- main/java/io/sentry
- time
- transport
- test/java/io/sentry
- time
- transport
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
5 | 9 | | |
6 | 10 | | |
7 | 11 | | |
| |||
19 | 23 | | |
20 | 24 | | |
21 | 25 | | |
| 26 | + | |
22 | 27 | | |
23 | 28 | | |
24 | 29 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
65 | | - | |
| 65 | + | |
66 | 66 | | |
67 | 67 | | |
68 | 68 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3654 | 3654 | | |
3655 | 3655 | | |
3656 | 3656 | | |
3657 | | - | |
| 3657 | + | |
3658 | 3658 | | |
3659 | 3659 | | |
3660 | 3660 | | |
| |||
7706 | 7706 | | |
7707 | 7707 | | |
7708 | 7708 | | |
| 7709 | + | |
7709 | 7710 | | |
7710 | 7711 | | |
7711 | 7712 | | |
| |||
7717 | 7718 | | |
7718 | 7719 | | |
7719 | 7720 | | |
| 7721 | + | |
| 7722 | + | |
| 7723 | + | |
| 7724 | + | |
| 7725 | + | |
| 7726 | + | |
7720 | 7727 | | |
7721 | 7728 | | |
7722 | 7729 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
22 | 25 | | |
23 | 26 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
32 | 33 | | |
33 | 34 | | |
34 | 35 | | |
| |||
58 | 59 | | |
59 | 60 | | |
60 | 61 | | |
61 | | - | |
| 62 | + | |
62 | 63 | | |
63 | 64 | | |
64 | 65 | | |
| |||
847 | 848 | | |
848 | 849 | | |
849 | 850 | | |
| 851 | + | |
850 | 852 | | |
851 | 853 | | |
852 | 854 | | |
| |||
1610 | 1612 | | |
1611 | 1613 | | |
1612 | 1614 | | |
| 1615 | + | |
1613 | 1616 | | |
1614 | 1617 | | |
1615 | 1618 | | |
| |||
2601 | 2604 | | |
2602 | 2605 | | |
2603 | 2606 | | |
| 2607 | + | |
2604 | 2608 | | |
2605 | 2609 | | |
2606 | 2610 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
| 28 | + | |
28 | 29 | | |
29 | | - | |
30 | | - | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
31 | 34 | | |
32 | 35 | | |
33 | 36 | | |
34 | 37 | | |
35 | | - | |
| 38 | + | |
36 | 39 | | |
37 | 40 | | |
38 | 41 | | |
| |||
0 commit comments