Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
Feat: Don't retry function upload on 400 or 422 status #478
Feat: Don't retry function upload on 400 or 422 status #478
Changes from 15 commits
a12f834
6eaf7b2
2f75b17
7d7c6a7
03e50c8
279e58b
7d176fb
de2b8c1
9b326af
6248a62
49e8d71
0116127
047bf94
2192c51
1367935
75e7e49
107dbe6
0276651
ff30a75
10097e7
25f5b63
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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.
Wondering if we could add a test here which exercises the new code paths we introduced (i.e. checking we don't retry
400
and422
errors when uploading).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.
@JGAntunes do you have any pointers for the testing? I seem to be a bit stuck here. We are also having trouble running the test suite locally, which is slowing this down a bit 😬
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.
about running the test suite locally, if it seems like nothing is running it's probably because of the retries loop.
try running the tests as:
And you should get some output (hopefully)
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.
Thanks for the tip @4xposed!! We got the tests running and can see the output which has been very helpful :D
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.
I think to properly assert the error message in the
requre.Equal
in line350
we need to make the mock server to return a body with a json that hascode:
andmessage
keys: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.
This is super helpful and definitely makes sense! -- looking at other test cases I see this is done similarly. However, when we set
rw.Write([]byte(`{"message": "Unprocessable Entity", "code": 422}`))
we keep getting the error&{0 } (*models.Error) is not supported by the TextConsumer, can be resolved by supporting TextUnmarshaler interface
.So then the apiError isn't set and then our test skips over the code we're trying to test and keeps retrying 🙈
Looking at other examples in other tests, it seems like it works to set the response this way when calling
client.Operations.UploadDeployFile
, but not when callingclient.uploadFiles
-- when callinguploadFiles
the error is thrown fromUploadDeployFile
.We've been trying to debug this by writing the body different ways, trying to marshal the response etc, but haven't had any success yet 🤔 Is there maybe something silly we're missing?
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.
This is where the error is being thrown from: https://github.com/netlify/open-api/blob/master/go/plumbing/operations/operations_client.go#L4131
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.
I think It might be the order on which those are set, mockserver is a bit quirky at times. try if setting the headers in this order helps:
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.
👋 @4xposed thanks so much for the tip! That worked and now as far as I can tell, the server is responding as expected. However, now we're hitting a different problem and struggling to debug it.
We now receive the error with the correct code and message, but when we get to this line
apiErr, ok := operationError.(apierrors.Error)
no matter what we try, apiErr is always
nil
andok
is always false.operationError
is anerror
that looks like:error(*github.com/netlify/open-api/v2/go/plumbing/operations.UploadDeployFunctionDefault) *{_statusCode: 422, Payload: *github.com/netlify/open-api/v2/go/models.Error {Code: 422, Message: "Unprocessable Entity"}}
In my debugger, I can access the status code by calling either
operationError._statusCode
oroperationError.Payload.Code
, but not by callingoperationError.(apierrors.Error)
. However, I can't calloperationError.Payload.Code
in the actual code, becausePayload
/Code
isn't defined on the Error type.So since
operationError.(apierrors.Error)
never seems to evaluate to anything and there wasn't a test for the original code, we're uncertain if we're doing something wrong here, or if the original code was actually working as intended.Are we missing something here? Is there a better way to test this (perhaps non-locally?)
cc @jrwhitmer @JGAntunes
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.
@4xposed Thanks, I really appreciate the offer! I'm in Europe now 🎉
Testing manually using the debugger, it looks like everything's working as expected, thanks so much for the fix. The one last thing I'm trying to do to wrap up this PR is to fix my tests:
doesn't work because the error's now wrapped by the
backoff.Permanent
error. Is it sufficient to justrequireError(t, err)
here? Or is there a better way to assert this that I'm missing?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.
Pairing might not be necessary since most of this seems to be working, but I'd appreciate you taking another look when you have the time 🙂
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.
we could call
err.Unwrap()
seems likebackoff.PermanentError
has a few methods for this: https://github.com/cenkalti/backoff/blob/v4/retry.go#L129I don't think it's strictly necessary, but it would be nice to at least have some way that we have the right error and not any error, if that makes sense.
What do you think?
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.
I'll give it a shot! I do agree it would be nice to have the right error if possible
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.
Okay, I used
Require. ErrorContains
instead and that seemed to do the trick for verifying we have the correct error messageThere 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.
The number of attempts doesn't seem to be consistent, so maybe there's a better way to assert this
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.
@4xposed this is one other tiny detail that sometimes makes the test fail - every once in a while it retries 13 times 🤔
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.
yes I think (emphasis on think) it retries infinitely until the
context
times out or it's cancelled.I think checking that there's more than 1 attempt (or some arbitrary number that's not too high) might be enough, maybe?
I will try to look more into the retry mechanism tomorrow morning to try to figure out if we can have more control in the test of how many times we retry
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.
I added a check to just make sure that the attempts are greater than 1 :) That should probably be sufficient for what we're testing