-
Notifications
You must be signed in to change notification settings - Fork 73
feat: enhance RateLimitException to return extra information #426
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,4 +5,26 @@ | |
* {@link RateLimiting} annotation. | ||
*/ | ||
public class RateLimitException extends RuntimeException { | ||
private final long retryAfterNanoSeconds; | ||
private final long remainingTokens; | ||
private final String configurationName; | ||
|
||
public RateLimitException(Long retryAfterNanoSeconds, Long remainingTokens, String configurationName) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't the cacheKey also of interest? |
||
super("Rate limit exceeded for configuration: " + configurationName + ". Retry after: " + (retryAfterNanoSeconds != null ? retryAfterNanoSeconds : 0) + "ns. Remaining tokens: " + (remainingTokens != null ? remainingTokens : 0)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not quite sure about it but can the remainingTokens be greater than 0? The message line is a little bit to long. my suggestion: super("Rate limit exceeded for configuration: " + configurationName + ". " +
"Retry after: " + toMilliseconds(retryAfterNanoSeconds) + "ns. " +
"Remaining tokens: " + toMilliseconds(remainingTokens)); // the slower variant
super("Rate limit exceeded for configuration %s : . Retry after: %sms . Remaining tokens: %s".formatted(
configurationName,
toMilliseconds(retryAfterNanoSeconds),
toMilliseconds(remainingTokens))
); private static long toMilliseconds(Long retryAfterNanoSeconds) {
return retryAfterNanoSeconds != null ? TimeUnit.NANOSECONDS.toMillis(retryAfterNanoSeconds) : 0;
} |
||
this.retryAfterNanoSeconds = retryAfterNanoSeconds != null ? retryAfterNanoSeconds : 0; | ||
this.remainingTokens = remainingTokens != null ? remainingTokens : 0; | ||
this.configurationName = configurationName; | ||
} | ||
|
||
public long getRetryAfterNanoSeconds() { | ||
return retryAfterNanoSeconds; | ||
} | ||
|
||
public long getRemainingTokens() { | ||
return remainingTokens; | ||
} | ||
|
||
public String getConfigurationName() { | ||
return configurationName; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,14 +80,19 @@ public void assert_no_rate_limit_with_skip_condition_matches() { | |
|
||
@Test | ||
public void assert_rate_limit_with_cache_key() { | ||
for(int i = 0; i < 5; i++) { | ||
// rate limit by parameter value | ||
for (int i = 0; i < 5; i++) { | ||
testService.withCacheKey("key1"); | ||
testService.withCacheKey("key2"); | ||
// all tokens consumed | ||
} | ||
assertThrows(RateLimitException.class, () -> testService.withCacheKey("key1")); | ||
assertThrows(RateLimitException.class, () -> testService.withCacheKey("key2")); | ||
RateLimitException ex1 = assertThrows(RateLimitException.class, () -> testService.withCacheKey("key1")); | ||
assertTrue(ex1.getRetryAfterNanoSeconds() >= 0); | ||
assertTrue(ex1.getRemainingTokens() >= 0); | ||
assertNotNull(ex1.getConfigurationName()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assertEquals("default", ex1.getConfigurationName()); |
||
|
||
RateLimitException ex2 = assertThrows(RateLimitException.class, () -> testService.withCacheKey("key2")); | ||
assertTrue(ex2.getRetryAfterNanoSeconds() >= 0); | ||
assertTrue(ex2.getRemainingTokens() >= 0); | ||
assertNotNull(ex2.getConfigurationName()); | ||
} | ||
|
||
@Test | ||
|
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.
Please use Lomboks @Getter