-
Notifications
You must be signed in to change notification settings - Fork 766
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
Retry based on Stripe-Should-Retry
and Retry-After
headers
#692
Conversation
b63cba4
to
0d3037a
Compare
d11d3dc
to
82f107b
Compare
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.
Some minor nits, but otherwise 🚢 🇮🇹
optional chaining
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.
LGTM!
cc @brandur-stripe to check the logic and make sure it's the one we want to apply to all client libraries.
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.
Generally looks good.
ptal @rattrayalex-stripe
@@ -228,21 +228,31 @@ StripeResource.prototype = { | |||
return true; | |||
} | |||
|
|||
// Retry on conflict and availability errors. | |||
if (res.statusCode === 409 || res.statusCode === 503) { | |||
if (res.headers && res.headers['stripe-should-retry'] === 'false') { |
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.
Can we put some docs on this to describe generally what Stripe-Should-Retry
is?
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.
Good idea, will do
if (res.headers && res.headers['stripe-should-retry'] === 'false') { | ||
return false; | ||
} | ||
if (res.headers && res.headers['stripe-should-retry'] === 'true') { |
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.
How does the interaction between Stripe-Should-Retry
and Retry-After
work?
I guess based on this condition being placed so early, if we're going to send Retry-After
, then Stripe-Should-Retry
is set to false
or not included? If so, doesn't that mean we have to fall back on other heuristics to decide whether to retry (like status code)?
I wonder if we should have it so that if there's a Retry-After
, Stripe-Should-Retry
is still set to an appropriate value that indicates whether a retry is appropriate. If we went down that route, we'd have to include a && !res.headers['stripe-retry-after']
in this check.
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.
if we're going to send Retry-After, then Stripe-Should-Retry is set to false or not included?
I assume you meant "true" not "false, and yes: I can share the internal doc, but our API should hold the invariant that if Retry-After
is set, Stripe-Should-Retry
should not be set to false
.
Were that to happen, though, I think Stripe-Should-Retry: false
should take precedence and block a Retry-After: X
, given that the likely intent of the latter is to ask clients to wait a little longer before retrying, and the intent of the former is to ask them not to retry at all (eg; because it will be futile or damaging).
In general, they're pretty orthogonal; technically, these should be separate PR's (I'm just lumping them together for convenience, since they came to mind at the same time).
Note that I think we'll ~always want to fall back to status code checks for at least some cases (eg; 500, 503, 504) in case the parts of our api stack that set Stripe-Should-Retry
are not hit.
I could see a case for dropping the code for 409
handling here and moving that into the API...
However, in general, we should expect the client to retry in some cases that the server does not make a recommendation, for example, 429's, where we do not retry but the client may choose to (but would hopefully respect Retry-After).
lib/StripeResource.js
Outdated
@@ -261,6 +271,11 @@ StripeResource.prototype = { | |||
// But never sleep less than the base sleep seconds. | |||
sleepSeconds = Math.max(initialNetworkRetryDelay, sleepSeconds); | |||
|
|||
// And never sleep less than the time the API asks us to wait, assuming it's a reasonable ask. | |||
if (Number.isInteger(retryAfter) && retryAfter <= 60) { |
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.
Can we constant-ize 60
here to make it more literate? Maybe MAX_RETRY_AFTER_WAIT
?
5c9b425
to
b24337d
Compare
Self-approving after adopting recommended changes |
As seen in stripe-node, adds support for the `Stripe-Should-Retry` header which is sent by the API when it explicitly would like us to either retry or _not_ retry. I'll add `Retry-After` separately at some point, but I punted it on it for now given that we're not using it yet. See: stripe/stripe-node#692
As seen in stripe-node, adds support for the `Stripe-Should-Retry` header which is sent by the API when it explicitly would like us to either retry or _not_ retry. I'll add `Retry-After` separately at some point, but I punted it on it for now given that we're not using it yet. See: stripe/stripe-node#692
As seen in stripe-node, adds support for the `Stripe-Should-Retry` header which is sent by the API when it explicitly would like us to either retry or _not_ retry. I'll add `Retry-After` separately at some point, but I punted it on it for now given that we're not using it yet. See: stripe/stripe-node#692
As seen in stripe-node, adds support for the `Stripe-Should-Retry` header which is sent by the API when it explicitly would like us to either retry or _not_ retry. I'll add `Retry-After` separately at some point, but I punted it on it for now given that we're not using it yet. See: stripe/stripe-node#692
r? @ob-stripe
cc @stripe/api-libraries @paulasjes-stripe @jlomas-stripe
This adds support for the
Stripe-Should-Retry
andRetry-After
headers.This allows the API to specify specific cases when an automatic retry is recommended (such as
lock_timeout
errors) or not recommended (such as when our idempotency framework would replay the request anyway).It also allows the API to encourage slower retries.