-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Fixes retry support to not fail due to body not being rewound between retry attempts. (#204+#196) #211
Conversation
If status code is >= 400: - Create a placeholder `APIError` (`ValidateResponseHandler`) - Unmarshal error from response, which may replace the above `APIError` - Test retryability of the error (`RetryHandler` - split out of `ValidateResponseHandler`) Added unit tests of retryable & unretryable 4xx responses.
Requests with POST bodies had their bodies consumed with the first request. If that request failed and was retried, the body was then empty. This caused a mismatch with the advertised Content-Length. Since this is a net/url error, not an aws.APIError, no further retries were attempted. As a result, no successful retries ever occurred. The fix is simple: Seek back to the beginning of the body before retrying.
This is more efficient than converting the string to a []byte.
… retry attempts. Merged #196 and #204 together along with other changes to make sure rewind works in all cases, Made sure the ordering of handler's setting Request.Retryable vs the Service.ShouldRetry are consitent. A Request Handler setting Request.Retryable will prevent RetryHandler calling Service.ShouldRetry. The Service's delay value wills still be applied though.
git fetch upstream pull/211/head:PR_211_fixRetries
git checkout PR_211_fixRetries where upstream is the remote: github.com/awslabs/aws-sdk-go, and PR_211_fixRetries is the local branch name to checkout this PR to. |
LGTM. I'd be tempted to go for an int instead of SettableBool -- see e.g. https://github.com/golang/tools/blob/master/cmd/vet/main.go#L56 -- but it is minor, and immaterial to the question at hand. It'll take a bit to get this integrated into our broader system, but if we still encounter problems then, I will diagnose...so full speed ahead! Thanks so much for the help with this. I look forward to the merge. :) |
I also like the idea of the triState pattern. Looks like we could use that more broadly in our config options too! |
- Moved retryable generic service exception to a map to maintainability - Added tests to verify ExpiredTokenException triggers retry Fixes #212
Any reason for preferring The reason for |
*bool requires an alloc. Also, accidentally copying a *bool can make different values alias. |
@josharian The 'Set' method requires a pointer receiver to mutate it, and so you get an allocation for using the given struct as well, right? See playground. With That's my reasoning for why I'd prefer Edit: I realized that you probably meant the |
The biggest argument I could see against using a pointer versus a type which knows if its wrapping value was set, is that with a pointer you must do nil checks before using the type's value. I don't think we plan on using triState itself from flag, but the idea I think is very useful in our config state. The idea we are thinking that a TriStateBool Get() will return either the zero value, or value set. If the user of TriStateBool cares if the value was actually set IsSet() can be used. It is my understanding that a pointer receiver means the object reference will be used and pointer to it will be provided to the function. Whereas not using a pointer receiver a copy of the receiver is made prior to being given to the function. This is why modifying a structure's property with a value receiver will not update the original structure's property the way you'd expect. e.g: http://play.golang.org/p/mNQxoUjGkM |
Glad to see this merged! Thanks, @jasdel. FWIW, @euank you don't use a Set method, you just assign a new value: http://play.golang.org/p/ZaGvE-9y_A. Tristate is pretty type-safe--attempting to use a Tristate where a bool is required will fail to compile. |
@josharian Yeah, per my edit I realized you meant tristate while typing my first paragraph and that my comment didn't actually apply. Sorry for the confusion there 😕 I recognize that it's type safe, but I still am concerned about the possibility for logic errors. If I type Because there's not a language-level construct of On the other hand, nil and pointers are core to the language and a typical Go developer will understand that a pointer might be nil, thus making logical errors far less likely. @jasdel The pointer requires nil checks, which I see as an argument for it, not against it. The tristate masks the third value somewhat, so you don't have to check for it, but you also might not realize you should check for it, leading to logically incorrect code. I do see the argument for tristate though and my opposition is only minor. |
Fixes the `cleanup_models.sh` script's hashbang to use correct syntax.
Fixes retry support to not fail due to body not being rewound between retry attempts.
Merged #196 and #204 together along with other changes to make sure rewind works in all cases, Made sure the ordering of handler's setting Request.Retryable vs the Service.ShouldRetry are consistent. A Request Handler setting Request.Retryable will prevent RetryHandler calling Service.ShouldRetry. The Service's delay value wills still be applied though.
Verified all tests pass and used @josharian's script to ping for aws request limits to verify retries were handled correctly.
Please try this out this PR and let me know if you hit retry failures still.