deal with 202 Accepted status code#488
deal with 202 Accepted status code#488caarlos0 wants to merge 11 commits intogoogle:masterfrom caarlos0:202
Conversation
There was a problem hiding this comment.
This change affects CheckResponse, which is an exported method. Its current documentation says:
// CheckResponse checks the API response for errors, and returns them if
// present. A response is considered an error if it has a status code outside
// the 200 range. API error responses are expected to have either no response
// body, or a JSON response body that maps to ErrorResponse. Any other
// response body will be silently ignored.
//
// The error type will be *RateLimitError for rate limit exceeded errors,
// and *TwoFactorAuthError for two-factor authentication errors.
func CheckResponse(r *http.Response) error {That is obviously no longer true, and needs to be updated to match reality. Specifically, this sentence "A response is considered an error if it has a status code outside the 200 range.", and the second paragraph should document that AcceptedError can be returned.
Also, you overlooked the first 3 lines of CheckResponse, which will cause this change to not work.
if c := r.StatusCode; 200 <= c && c <= 299 {
return nil
}That'll need to be updated too.
github/github.go
Outdated
| } | ||
| return abuseRateLimitError | ||
| case r.StatusCode == http.StatusAccepted: | ||
| return &AcceptedError{} |
There was a problem hiding this comment.
I'm tempted to suggest we turn this into a value rather than a pointer. It's an empty struct. Pointer seems unneeded and unhelpful.
return AcceptedError{}
github/github.go
Outdated
| type AcceptedError struct{} | ||
|
|
||
| func (r *AcceptedError) Error() string { | ||
| return "Job scheduled on GitHub side, try again later" |
There was a problem hiding this comment.
Error strings should not be capitalized. See https://github.com/golang/go/wiki/CodeReviewComments#error-strings.
github/github.go
Outdated
| // the information needed and cache it. | ||
| type AcceptedError struct{} | ||
|
|
||
| func (r *AcceptedError) Error() string { |
There was a problem hiding this comment.
Receiver is unused and can be removed. See rationale here.
| // AcceptedError occurs when GitHub returns 202 Accepted response with an | ||
| // empty body, which means a job was scheduled on the GitHub side to process | ||
| // the information needed and cache it. | ||
| type AcceptedError struct{} |
There was a problem hiding this comment.
I'm not sure if it's obvious or worth adding another sentence to the current documentation, something like:
Technically, 202 Accepted is not a real error, it's just used to indicate that results are not ready yet, but should be available soon. The request should be repeated after some time.
The part that's missing to me is that the documentation should indicate that the this is a "retryable" error. Trying again after some time is completely normal and expected to succeed (but maybe not on the first try).
|
@shurcooL thanks for the review! I think I fixed everything, I still not sure about the messages docs wording though. Thanks! |
dmitshur
left a comment
There was a problem hiding this comment.
This is starting to look good.
See an inline comment. Additionally, I think this PR would benefit significantly if we can document the endpoints where AcceptedError can be returned. As far as I can tell, it'd be the 5 endpoints listed at https://developer.github.com/v3/repos/statistics/. Do you know/think any others can return 202?
An alternative is to document AcceptedError in doc.go package documentation. That'd be easier, but not as helpful IMO.
| // response body will be silently ignored. | ||
| // | ||
| // The error type will be *RateLimitError for rate limit exceeded errors, | ||
| // and *TwoFactorAuthError for two-factor authentication errors. |
There was a problem hiding this comment.
Let's mention AcceptedError here.
// The error type will be *RateLimitError for rate limit exceeded errors,
// AcceptedError for 202 Accepted status codes,
// and *TwoFactorAuthError for two-factor authentication errors.
This makes me realize that there's actually a good reason to revert back to using a pointer to *AcceptedError rather than value: for consistency of type assertion code to other error types. Currently, it'd be:
switch err.(type) {
case *github.RateLimitError:
// handle rate limit exceeded error
case *github.TwoFactorAuthError:
// handle two-factor authentication error
case github.AcceptedError: // inconsistent
// handle accepted error
}If we revert to using a pointer to *AcceptedError, it becomes consistent.
switch err.(type) {
case *github.RateLimitError:
// handle rate limit exceeded error
case *github.TwoFactorAuthError:
// handle two-factor authentication error
case *github.AcceptedError: // consistent
// handle accepted error
}I think that's a good argument to use pointer here too. Do you agree?
There was a problem hiding this comment.
Yes, I agree... looks more consistent indeed
|
However, at this point I'd like to ping @willnorris or @gmlewis to take a look at this API change to Also, it's kinda going against the HTTP spec which says that 2xx range status codes are "success" cases. But I think in Go it's expected/most idiomatic to return a non-nil error whenever the result you asked for cannot be returned to you. My main argument for this change in #486 (comment) was:
|
I did some search and found:
Seems like the BTW I found this by searching for |
Thanks for doing that. Thinking more about it, I think we should document the 202 Accepted status being translated into How about adding a new section to the package doc.go (also to README.md, the two should be in sync now) then. It could mention when Feel free to delay working on this until we hear from another maintainer of this library that this is a good change to go with. |
| // repository, this method will return an *AcceptedError and a status code of | ||
| // 202. This is because this is the status that github returns to signify that | ||
| // it is now computing the requested statistics. A follow up request, after a | ||
| // delay of a second or so, should result in a successful request. |
There was a problem hiding this comment.
Oh, I didn't see we already had that written up. In that case, it makes a lot of sense to update it as you've done, and copy it over to the other methods (as you've also already done).
There was a problem hiding this comment.
Yeah, I haven't seen that before either =)
|
@shurcooL agreed, done. |
|
We found a Contributor License Agreement for you (the sender of this pull request) and all commit authors, but as best as we can tell these commits were authored by someone else. If that's the case, please add them to this pull request and have them confirm that they're okay with these commits being contributed to Google. If we're mistaken and you did author these commits, just reply here to confirm. |
Plus a few other minor changes for improved consistency.
README.md
Outdated
| **Build Status:** [](https://travis-ci.org/google/go-github) | ||
| **Documentation:** [](https://godoc.org/github.com/google/go-github/github) | ||
| **Mailing List:** [go-github@googlegroups.com](https://groups.google.com/group/go-github) | ||
| **Build Status:** [](https://travis-ci.org/google/go-github) |
There was a problem hiding this comment.
You should undo these changes. I'm guessing your editor did them for you.
The two spaces at the end of those lines are significant, they mark a line break after each line.
Compare what the README looks like now:
And after this change, it's less readable:
What's been approved are the changes to my previous "request changes" review, not the entire PR.
|
To make the latest status of this PR more visible, I'm waiting to hear from @gmlewis or another maintainer on their thoughts. All my feedback so far has already been addressed. That said, I'm more confident this is a good direction after realizing that the following is already the current behavior for So this PR is about turning "non-nil error" into "*AcceptedError", not something more drastic as I originally thought. |
|
Included in 231da32. |
|
Thanks @gmlewis 👍 |
Fixes google#486. Closes google#488. Change-Id: I31ff003552dbffaca78c740b89d54150b81c525c


When github returns a 202, it means that they don't have the data you asked, and it is considered a rater heavy operation to get it, so they schedule a background job to fetch and cache it, and subsequent calls to it might work.
go-github was failing to deal with that, because in some places it was trying to parse the body to a list of some object, and github actually returns a
{}.With this change we would be able to do the same as we do with rate limiting issues, e.g.:
fixes #486