Skip to content
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

Add explicit handling for rate-limit errors #1033

Merged
merged 8 commits into from
May 3, 2024

Conversation

mthadley
Copy link
Contributor

Description

Introduces a new RateLimitExceededException to be thrown when a 429 error is encountered, rather than defaulting to a more generic error exception class.

This also allows the reading of the Retry-After header, which is helpful for clients to retry, as well as debugging.

There's also some light refactoring included.

Documentation

Does this require changes to the WorkOS Docs? E.g. the API Reference or code snippets need updates.

[ ] Yes

If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.

@mthadley mthadley requested a review from a team as a code owner April 25, 2024 23:10
@@ -0,0 +1,5 @@
export interface RequestException {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my initial pass I realized the new RateLimitExceededException was missing status. It seemed worth having something like this in order for all exception classes to be roughly shaped the same.

Arguable we should have a base-class instead, but I opted for an interface for now since it only adds an additional compile-time check, and we can decide later.

Comment on lines +218 to +226
case 429: {
const retryAfter = headers.get('Retry-After');

throw new RateLimitExceededException(
data.message,
requestID,
retryAfter ? Number(retryAfter) : null,
);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a breaking change?

Existing users may be doing an error instanceof GenericServerException when attempting to handle rate limit errors, which would no longer work with the introduction of this new exception.

Copy link
Contributor Author

@mthadley mthadley Apr 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, one option would be to make GenericServerException the actual base-class that the other exceptions extend from. It can enforce that rough shape we want all of them to have, and would mean this is no longer a potential breaking-change.

Though I'd like to hear opinions before I make that change.

EDIT: It might be a breaking change either way since even if the base class stays the same, the name will not, and folks may be relying on that, too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strongly prefer having GenericServerException be the base-class for inheritance to make this not be a breaking change. We want to generally shy away from releasing major versions too frequently.

While someone out there might be relying on the name, I feel that that's a bit of an anti-pattern over checking instanceof. I'm comfortable with releasing this as a minor version instead of a major.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made the minimal change of only having the new exception inherit from GenericServerException, though a large change could be to have all of the requests also inherit (and left a note about it): 4af4a79.

Comment on lines +218 to +226
case 429: {
const retryAfter = headers.get('Retry-After');

throw new RateLimitExceededException(
data.message,
requestID,
retryAfter ? Number(retryAfter) : null,
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strongly prefer having GenericServerException be the base-class for inheritance to make this not be a breaking change. We want to generally shy away from releasing major versions too frequently.

While someone out there might be relying on the name, I feel that that's a bit of an anti-pattern over checking instanceof. I'm comfortable with releasing this as a minor version instead of a major.

it('throws a RateLimitExceededException', async () => {
fetchOnce(
{
message: 'Too many requests',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this verbatim what we return from the API? I'd like there to be more information in here, like a link to the rate limiting docs or a callout to reach out on support@ if they want to discuss higher rate limits.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, and agreed that we should have more information in the message. Separately, I can look into updating that, adding the additional details you mentioned, so that all SDK's (or no SDK at all) will have the extra context.

},
{
status: 429,
headers: { 'X-Request-ID': 'a-request-id', 'Retry-After': '10' },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is 10 seconds the default or is that just for this test? If it's the default returned by the API then that feels way too high.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a test value. IIRC, the actual Retry-After is generally larger, and varies by endpoint.

@mthadley mthadley requested a review from PaulAsjes May 2, 2024 22:36
@mthadley mthadley merged commit 3c2c81f into main May 3, 2024
4 checks passed
@mthadley mthadley deleted the add-rate-limit-error-handling branch May 3, 2024 20:06
PaulAsjes pushed a commit that referenced this pull request May 8, 2024
Introduces a new `RateLimitExceededException` to be thrown when a `429`
error is encountered, rather than defaulting to a more generic error
exception class.

This also allows the reading of the `Retry-After` header, which is
helpful for clients to retry, as well as debugging.

There's also some light refactoring included.

Does this require changes to the WorkOS Docs? E.g. the [API
Reference](https://workos.com/docs/reference) or code snippets need
updates.

```
[ ] Yes
```

If yes, link a related docs PR and add a docs maintainer as a reviewer.
Their approval is required.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants