Skip to content

Commit 33fa99a

Browse files
authored
Add options bag to PollUntilDone method (Azure#17693)
* Add options bag to PollUntilDone method Passing nil/zero-value options defaults to 30s polling frequency. * don't mutate caller's options * update changelog
1 parent d2f6ad6 commit 33fa99a

File tree

5 files changed

+59
-26
lines changed

5 files changed

+59
-26
lines changed

sdk/azcore/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* Renamed `cloud.Configuration.LoginEndpoint` to `.ActiveDirectoryAuthorityHost`
99
* Removed `AuxiliaryTenants` field from `arm/ClientOptions` and `arm/policy/BearerTokenOptions`
1010
* Removed `TokenRequestOptions.TenantID`
11+
* `Poller[T].PollUntilDone()` now takes an `options *PollUntilDoneOptions` param instead of `freq time.Duration`
1112

1213
### Bugs Fixed
1314

sdk/azcore/arm/runtime/poller.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,20 +134,36 @@ func NewPollerFromResumeToken[T any](token string, pl runtime.Pipeline, options
134134
}, nil
135135
}
136136

137+
// PollUntilDoneOptions contains the optional values for the Poller[T].PollUntilDone() method.
138+
type PollUntilDoneOptions struct {
139+
// Frequency is the time to wait between polling intervals in absence of a Retry-After header. Allowed minimum is one second.
140+
// Pass zero to accept the default value (30s).
141+
Frequency time.Duration
142+
}
143+
137144
// Poller encapsulates a long-running operation, providing polling facilities until the operation reaches a terminal state.
138145
type Poller[T any] struct {
139146
pt *pollers.Poller
140147
rt *T
141148
}
142149

143150
// PollUntilDone will poll the service endpoint until a terminal state is reached, an error is received, or the context expires.
144-
// freq: the time to wait between intervals in absence of a Retry-After header. Allowed minimum is one second.
145-
func (p *Poller[T]) PollUntilDone(ctx context.Context, freq time.Duration) (T, error) {
151+
// options: pass nil to accept the default values.
152+
// NOTE: the default polling frequency is 30 seconds which works well for most services. However, some services might
153+
// benefit from a shorter or longer duration.
154+
func (p *Poller[T]) PollUntilDone(ctx context.Context, options *PollUntilDoneOptions) (T, error) {
155+
if options == nil {
156+
options = &PollUntilDoneOptions{}
157+
}
158+
cp := *options
159+
if cp.Frequency == 0 {
160+
cp.Frequency = 30 * time.Second
161+
}
146162
var resp T
147163
if p.rt != nil {
148164
resp = *p.rt
149165
}
150-
_, err := p.pt.PollUntilDone(ctx, freq, &resp)
166+
_, err := p.pt.PollUntilDone(ctx, cp.Frequency, &resp)
151167
return resp, err
152168
}
153169

sdk/azcore/arm/runtime/poller_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func TestNewPollerAsync(t *testing.T) {
9393
if err != nil {
9494
t.Fatal(err)
9595
}
96-
result, err := poller.PollUntilDone(context.Background(), time.Second)
96+
result, err := poller.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
9797
if err != nil {
9898
t.Fatal(err)
9999
}
@@ -128,7 +128,7 @@ func TestNewPollerBody(t *testing.T) {
128128
if err != nil {
129129
t.Fatal(err)
130130
}
131-
result, err := poller.PollUntilDone(context.Background(), time.Second)
131+
result, err := poller.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
132132
if err != nil {
133133
t.Fatal(err)
134134
}
@@ -203,7 +203,7 @@ func TestNewPollerInitialRetryAfter(t *testing.T) {
203203
if pt := pollers.PollerType(poller.pt); pt != reflect.TypeOf(&async.Poller{}) {
204204
t.Fatalf("unexpected poller type %s", pt.String())
205205
}
206-
result, err := poller.PollUntilDone(context.Background(), time.Second)
206+
result, err := poller.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
207207
if err != nil {
208208
t.Fatal(err)
209209
}
@@ -266,7 +266,7 @@ func TestNewPollerFailedWithError(t *testing.T) {
266266
if pt := pollers.PollerType(poller.pt); pt != reflect.TypeOf(&async.Poller{}) {
267267
t.Fatalf("unexpected poller type %s", pt.String())
268268
}
269-
_, err = poller.PollUntilDone(context.Background(), time.Second)
269+
_, err = poller.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
270270
if err == nil {
271271
t.Fatal(err)
272272
}
@@ -301,7 +301,7 @@ func TestNewPollerSuccessNoContent(t *testing.T) {
301301
if err != nil {
302302
t.Fatal(err)
303303
}
304-
result, err := poller.PollUntilDone(context.Background(), time.Second)
304+
result, err := poller.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
305305
if err != nil {
306306
t.Fatal(err)
307307
}
@@ -363,7 +363,7 @@ func TestNewPollerWithResponseType(t *testing.T) {
363363
if err != nil {
364364
t.Fatal(err)
365365
}
366-
result, err := poller.PollUntilDone(context.Background(), time.Second)
366+
result, err := poller.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
367367
if err != nil {
368368
t.Fatal(err)
369369
}

sdk/azcore/runtime/poller.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,20 +123,36 @@ func NewPollerFromResumeToken[T any](token string, pl exported.Pipeline, options
123123
}, nil
124124
}
125125

126+
// PollUntilDoneOptions contains the optional values for the Poller[T].PollUntilDone() method.
127+
type PollUntilDoneOptions struct {
128+
// Frequency is the time to wait between polling intervals in absence of a Retry-After header. Allowed minimum is one second.
129+
// Pass zero to accept the default value (30s).
130+
Frequency time.Duration
131+
}
132+
126133
// Poller encapsulates a long-running operation, providing polling facilities until the operation reaches a terminal state.
127134
type Poller[T any] struct {
128135
pt *pollers.Poller
129136
rt *T
130137
}
131138

132139
// PollUntilDone will poll the service endpoint until a terminal state is reached, an error is received, or the context expires.
133-
// freq: the time to wait between intervals in absence of a Retry-After header. Allowed minimum is one second.
134-
func (p *Poller[T]) PollUntilDone(ctx context.Context, freq time.Duration) (T, error) {
140+
// options: pass nil to accept the default values.
141+
// NOTE: the default polling frequency is 30 seconds which works well for most services. However, some services might
142+
// benefit from a shorter or longer duration.
143+
func (p *Poller[T]) PollUntilDone(ctx context.Context, options *PollUntilDoneOptions) (T, error) {
144+
if options == nil {
145+
options = &PollUntilDoneOptions{}
146+
}
147+
cp := *options
148+
if cp.Frequency == 0 {
149+
cp.Frequency = 30 * time.Second
150+
}
135151
var resp T
136152
if p.rt != nil {
137153
resp = *p.rt
138154
}
139-
_, err := p.pt.PollUntilDone(ctx, freq, &resp)
155+
_, err := p.pt.PollUntilDone(ctx, cp.Frequency, &resp)
140156
return resp, err
141157
}
142158

sdk/azcore/runtime/poller_test.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func TestLocPollerSimple(t *testing.T) {
9696
}
9797
var respFromCtx *http.Response
9898
ctxWithResp := WithCaptureResponse(context.Background(), &respFromCtx)
99-
_, err = lro.PollUntilDone(ctxWithResp, time.Second)
99+
_, err = lro.PollUntilDone(ctxWithResp, &PollUntilDoneOptions{Frequency: time.Second})
100100
if err != nil {
101101
t.Fatal(err)
102102
}
@@ -129,7 +129,7 @@ func TestLocPollerWithWidget(t *testing.T) {
129129
if !closed() {
130130
t.Fatal("initial response body wasn't closed")
131131
}
132-
w, err := lro.PollUntilDone(context.Background(), time.Second)
132+
w, err := lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
133133
if err != nil {
134134
t.Fatal(err)
135135
}
@@ -162,7 +162,7 @@ func TestLocPollerCancelled(t *testing.T) {
162162
if !closed() {
163163
t.Fatal("initial response body wasn't closed")
164164
}
165-
w, err := lro.PollUntilDone(context.Background(), time.Second)
165+
w, err := lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
166166
if err == nil {
167167
t.Fatal("unexpected nil error")
168168
}
@@ -198,7 +198,7 @@ func TestLocPollerWithError(t *testing.T) {
198198
if !closed() {
199199
t.Fatal("initial response body wasn't closed")
200200
}
201-
w, err := lro.PollUntilDone(context.Background(), time.Second)
201+
w, err := lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
202202
if err == nil {
203203
t.Fatal("unexpected nil error")
204204
}
@@ -256,7 +256,7 @@ func TestLocPollerWithResumeToken(t *testing.T) {
256256
if err != nil {
257257
t.Fatal(err)
258258
}
259-
_, err = lro.PollUntilDone(context.Background(), time.Second)
259+
_, err = lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
260260
if err != nil {
261261
t.Fatal(err)
262262
}
@@ -286,7 +286,7 @@ func TestLocPollerWithTimeout(t *testing.T) {
286286
t.Fatal("initial response body wasn't closed")
287287
}
288288
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
289-
_, err = lro.PollUntilDone(ctx, time.Second)
289+
_, err = lro.PollUntilDone(ctx, &PollUntilDoneOptions{Frequency: time.Second})
290290
cancel()
291291
if err == nil {
292292
t.Fatal("unexpected nil error")
@@ -325,7 +325,7 @@ func TestOpPollerSimple(t *testing.T) {
325325
if !closed() {
326326
t.Fatal("initial response body wasn't closed")
327327
}
328-
_, err = lro.PollUntilDone(context.Background(), time.Second)
328+
_, err = lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
329329
if err != nil {
330330
t.Fatal(err)
331331
}
@@ -365,7 +365,7 @@ func TestOpPollerWithWidgetPUT(t *testing.T) {
365365
if !closed() {
366366
t.Fatal("initial response body wasn't closed")
367367
}
368-
w, err := lro.PollUntilDone(context.Background(), time.Second)
368+
w, err := lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
369369
if err != nil {
370370
t.Fatal(err)
371371
}
@@ -409,7 +409,7 @@ func TestOpPollerWithWidgetPOSTLocation(t *testing.T) {
409409
if !closed() {
410410
t.Fatal("initial response body wasn't closed")
411411
}
412-
w, err := lro.PollUntilDone(context.Background(), time.Second)
412+
w, err := lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
413413
if err != nil {
414414
t.Fatal(err)
415415
}
@@ -451,7 +451,7 @@ func TestOpPollerWithWidgetPOST(t *testing.T) {
451451
if !closed() {
452452
t.Fatal("initial response body wasn't closed")
453453
}
454-
w, err := lro.PollUntilDone(context.Background(), time.Second)
454+
w, err := lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
455455
if err != nil {
456456
t.Fatal(err)
457457
}
@@ -496,7 +496,7 @@ func TestOpPollerWithWidgetResourceLocation(t *testing.T) {
496496
if !closed() {
497497
t.Fatal("initial response body wasn't closed")
498498
}
499-
w, err := lro.PollUntilDone(context.Background(), time.Second)
499+
w, err := lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
500500
if err != nil {
501501
t.Fatal(err)
502502
}
@@ -559,7 +559,7 @@ func TestOpPollerWithResumeToken(t *testing.T) {
559559
if err != nil {
560560
t.Fatal(err)
561561
}
562-
_, err = lro.PollUntilDone(context.Background(), time.Second)
562+
_, err = lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
563563
if err != nil {
564564
t.Fatal(err)
565565
}
@@ -592,7 +592,7 @@ func TestNopPoller(t *testing.T) {
592592
if resp != firstResp {
593593
t.Fatal("unexpected response")
594594
}
595-
_, err = lro.PollUntilDone(context.Background(), time.Second)
595+
_, err = lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
596596
if err != nil {
597597
t.Fatal(err)
598598
}
@@ -648,7 +648,7 @@ func TestOpPollerWithResponseType(t *testing.T) {
648648
if !closed() {
649649
t.Fatal("initial response body wasn't closed")
650650
}
651-
w, err := lro.PollUntilDone(context.Background(), time.Second)
651+
w, err := lro.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Second})
652652
if err != nil {
653653
t.Fatal(err)
654654
}

0 commit comments

Comments
 (0)