Skip to content

Commit 3c80879

Browse files
authored
Don't consider 429 as terminal failure for Location poller (#22651)
If the polling request is being throttled, preserve the current state and return the *http.Response.
1 parent a25e0d3 commit 3c80879

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

sdk/azcore/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
### Bugs Fixed
1414

1515
* `runtime.SetMultipartFormData` won't try to stringify `[]byte` values.
16+
* Pollers that use the `Location` header won't consider `http.StatusTooManyRequests` a terminal failure.
1617

1718
### Other Changes
1819

sdk/azcore/internal/pollers/loc/loc.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
103103
} else if resp.StatusCode > 199 && resp.StatusCode < 300 {
104104
// any 2xx other than a 202 indicates success
105105
p.CurState = poller.StatusSucceeded
106+
} else if resp.StatusCode == http.StatusTooManyRequests {
107+
// the request is being throttled. we DO NOT want to
108+
// include this as terminal failure so preserve the
109+
// existing state and return the response.
106110
} else {
107111
p.CurState = poller.StatusFailed
108112
}

sdk/azcore/internal/pollers/loc/loc_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
1818
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
19+
"github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
1920
"github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
2021
"github.com/stretchr/testify/require"
2122
)
@@ -173,3 +174,26 @@ func TestSynchronousCompletion(t *testing.T) {
173174
require.Equal(t, poller.StatusSucceeded, lp.CurState)
174175
require.True(t, lp.Done())
175176
}
177+
178+
func TestWithThrottling(t *testing.T) {
179+
srv, close := mock.NewServer()
180+
defer close()
181+
srv.AppendResponse(mock.WithStatusCode(http.StatusTooManyRequests))
182+
srv.AppendResponse(mock.WithStatusCode(http.StatusAccepted))
183+
srv.AppendResponse(mock.WithStatusCode(http.StatusTooManyRequests))
184+
srv.AppendResponse(mock.WithStatusCode(http.StatusOK))
185+
resp := initialResponse()
186+
resp.Header.Set(shared.HeaderLocation, srv.URL())
187+
lp, err := New[struct{}](exported.NewPipeline(shared.TransportFunc(func(req *http.Request) (*http.Response, error) {
188+
return srv.Do(req)
189+
})), resp)
190+
require.NoError(t, err)
191+
respCount := 0
192+
for !lp.Done() {
193+
_, err = lp.Poll(context.Background())
194+
require.NoError(t, err)
195+
respCount++
196+
}
197+
require.EqualValues(t, 4, respCount)
198+
require.EqualValues(t, poller.StatusSucceeded, lp.CurState)
199+
}

0 commit comments

Comments
 (0)