Added functionality to retry in Invoke-RestMethod and Invoke-WebRequest.#5760
Added functionality to retry in Invoke-RestMethod and Invoke-WebRequest.#5760iSazonov merged 21 commits intoPowerShell:masterfrom
Conversation
There was a problem hiding this comment.
Please add a more meaningful summary. Capitalize the first word and end with a period.
There was a problem hiding this comment.
Please add a more meaningful summary. Capitalize the first word and end with a period.
There was a problem hiding this comment.
Can you investigate collapsing this to a single do/while instead of nested?
There was a problem hiding this comment.
I think we should have the retry logic in GetResponse() rather than ProcessRecord().
There was a problem hiding this comment.
Moved logic to GetResponse()
There was a problem hiding this comment.
We should probably dispose the current HttpResponseMessage before retrying.
There was a problem hiding this comment.
This should move to the end of the previous line.
There was a problem hiding this comment.
I believe it would be better to have RetryCount and RetryIntervalSec set on WebSession in PrepareSession() and then have this area of code retrieve the values from WebSession. It would mean extending WebRequestSession to include new Properties, but I believe that is the correct direction for these settings.
There was a problem hiding this comment.
This current logic leads to an interestingly weird combination. If you set -MaximumRedirection 0 -RetryCount 5 -RetryIntervalSec 1 and the response code is 301, this will still retry the same link 5 times because HttpResponseMessage.IsSuccessStatusCode is only true for response codes 200-299 inclusive... not sure how to rectify that.
There was a problem hiding this comment.
also... since the logic for reducing the current redirection count is handled in GetResponse(), we may need to reset WebSession.MaximumRedirection to the MaximumRedirection property value before continuing.
There was a problem hiding this comment.
Best that I can find, the HTTP spec doesn't say enough about rate limiting to make it something we can depend on reliably. However, I think we can say that retry only occurs on a 429 or 403 and document it as such unless there's data showing that web services are using other error codes.
There was a problem hiding this comment.
@SteveL-MSFT I can see other usecases for this beyond just rate limiting. I could see using this to test 404 errors until a new page comes online after a publish/push and it $x attempts fail alert that the push/publish failed.
Perhaps it we limit it to 400-499 inclusive it would be best. In my experience with APIs I have seen more than 403 and 429 used for busy endpoints (including 404... Reddit... ugh) or rate limiting, but it's always a 400 level error
There was a problem hiding this comment.
@markekraus that's a fair point. I think 4xx would be fine.
There was a problem hiding this comment.
After further consideration, this should work for the following status codes: 304. 400-599 inclusive
304 could be used for monitoring the change of a resource and is not a redirect status even though it in the 300 range. Retries on 5XX errors makes perfect sense to overcome temporary service glitches and cloudflare shenanigans.
There was a problem hiding this comment.
See my comment about setting and retrieving RetryIntervalSec and RetryCount from WebSession.
There was a problem hiding this comment.
Perhaps we should default to 1 min instead of 10 secs to be more polite.
There was a problem hiding this comment.
I think we should have the retry logic in GetResponse() rather than ProcessRecord().
There was a problem hiding this comment.
Best that I can find, the HTTP spec doesn't say enough about rate limiting to make it something we can depend on reliably. However, I think we can say that retry only occurs on a 429 or 403 and document it as such unless there's data showing that web services are using other error codes.
There was a problem hiding this comment.
This won't work once we start localizing the error messages
There was a problem hiding this comment.
I don't really like this test. I'd rather have a real failure emulated by WebListener. Add a new endpoint which take a session ID (new GUID), a status code, and a fail count. Until the initially provided fail count is reached when using that session ID it produces a response with the provided status code After fail count is reached it returns a normal 200 response. The response body should include the request count for the given session ID. This way we can test how it reacts with various responses and differing fail counts provided by actual endpoint errors instead of relying on fake logic to enter the code path and without relying on verbose messages.
|
@adityapatwardhan Could you please continue? |
|
@adityapatwardhan Please resolve conflicts. |
|
I plan to resume work on this next week. |
|
Did you consider implementing Exponential Backof or different retry strategies? AWS SDKs for instance use an Exponential Backof and it is good practice for many other web services. |
|
@ffeldhaus Please open new Issue for your great suggestion - we shouldn't lost this. |
|
I thought about this feature some more and I don't think it should be included in the current form without further discussion to prevent retries to cause issues or unwanted behavior and I don't think a Pull Request is the right place to discuss the design of this feature. As issue #5582 was already created for this feature, we should first discuss the design there and then continue with the Pull Request. I will add my concerns and design ideas to issue #5582. |
|
This PR has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed if no further activity occurs within 10 days. |
|
We have #6447 - should we close the Issue? |
|
This PR has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed if no further activity occurs within 10 days. |
|
I wouldn't want to lose this. |
|
@markekraus Updated test and controller with echo for sessionId. |
|
@adityapatwardhan Two more things and I think this will be done. I just realized there are only tests for |
|
@markekraus Since the code path is same, I believe adding all the tests will be duplication. I will add one test for Invoke-RestMethod to cover the scenario. |
|
@adityapatwardhan The convention for the web cmdlets is to test all features on both, even common features. There is always the possibility that the common features clash with the implementation features. |
|
@markekraus Please review again. I have added tests for |
|
@adityapatwardhan there is a for example, and |
|
@markekraus I decided to go with a separate Let me know your thoughts? |
|
@adityapatwardhan For all new features they have been separate context blocks in the top level describe blocks for each cmdlet. I'd prefer to stick to this pattern for now and look at changing things up in one of the open issues I have on refactoring the code and tests. |
|
@markekraus Ok, agreed. I will send an update in a few minutes. |
|
@markekraus Made the changes to the tests as discussed above. |
|
|
||
| Context "Invoke-WebRequest retry tests" { | ||
|
|
||
| It "<Command> can retry - <Name>" -TestCases @( |
There was a problem hiding this comment.
<Command> -> Invoke-WebRequest since it's no longer in the testcases hash.
| $jsonError.error | Should -BeExactly 'Error: HTTP - 400 occurred.' | ||
| } | ||
|
|
||
| It "<Command> can retry with POST" { |
There was a problem hiding this comment.
<Command> -> Invoke-WebRequest since it's no longer in the testcases hash.
|
@markekraus Good catch! Fixed. |
markekraus
left a comment
There was a problem hiding this comment.
One final thing. Sorry :(
test/tools/WebListener/README.md
Outdated
|
|
||
| ```json | ||
| { | ||
| "failureResponsesSent":2 |
There was a problem hiding this comment.
Can you update this to include the sessionId that is now also returned.
|
@markekraus Fixed documentation. |
markekraus
left a comment
There was a problem hiding this comment.
@adityapatwardhan Thanks for you patience and diligence. LGTM
|
Reopen to restart CIs. |
|
@iSazonov Thanks for restarting CIs. All tests passed, ready to merge? |
|
@adityapatwardhan Thanks for great contribution! |
Fixes #5582
PR Summary
The change added two parameters,
RetryCountandRetryIntervalSecto enable retry functionality.When retrying a verbose message is sent out to inform the user.
PR Checklist
Note: Please mark anything not applicable to this PR
NA.[feature]if the change is significant or affectes feature testsWIP:to the beginning of the title and remove the prefix when the PR is ready.