Skip to content

Commit bd85dcc

Browse files
authored
Merge pull request #1448 from ydb-platform/fix-flap-TestDoCreateSessionError
added lastErr from previous attemp in retry.RetryWithResult
2 parents a431646 + 6fe547c commit bd85dcc

File tree

5 files changed

+48
-33
lines changed

5 files changed

+48
-33
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
* Added `lastErr` from previous attempt in `retry.RetryWithResult`
2+
13
## v3.80.0
24
* Replaced internal table client pool entities to `internal/pool`
35

internal/credentials/oauth2_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ func TestOauth2TokenExchange(t *testing.T) {
145145
Status: http.StatusForbidden,
146146
ExpectedToken: "",
147147
ExpectedError: errCouldNotExchangeToken,
148-
ExpectedErrorPart: "403 Forbidden, description: \"something went bad\", error_uri: my_error_uri",
148+
ExpectedErrorPart: "403 Forbidden, description: \\\"something went bad\\\", error_uri: my_error_uri",
149149
},
150150
{
151151
Response: `{"access_token":"test_token","token_type":"","expires_in":42,"some_other_field":"x"}`,
@@ -170,7 +170,7 @@ func TestOauth2TokenExchange(t *testing.T) {
170170
Status: http.StatusOK,
171171
ExpectedToken: "",
172172
ExpectedError: errDifferentScope,
173-
ExpectedErrorPart: "Expected \"test_scope1 test_scope2\", but got \"s\"",
173+
ExpectedErrorPart: "Expected \\\"test_scope1 test_scope2\\\", but got \\\"s\\\"",
174174
},
175175
{
176176
Response: `{"access_token":"","token_type":"Bearer","expires_in":42}`,

internal/pool/pool.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ func (p *Pool[PT, T]) With(
348348
opts ...retry.Option,
349349
) (finalErr error) {
350350
var attempts int
351+
351352
if onWith := p.config.trace.OnWith; onWith != nil {
352353
onDone := onWith(&ctx,
353354
stack.FunctionID("github.com/ydb-platform/ydb-go-sdk/v3/internal/pool.(*Pool).With"),
@@ -608,25 +609,27 @@ func (p *Pool[PT, T]) getItem(ctx context.Context) (item PT, finalErr error) { /
608609
}
609610
}
610611

611-
item, createItemErr := p.createItem(ctx)
612+
item, err := p.createItem(ctx)
612613
if item != nil {
613614
return item, nil
614615
}
615616

616-
if !isRetriable(createItemErr) {
617-
return nil, xerrors.WithStackTrace(createItemErr)
617+
if !isRetriable(err) {
618+
return nil, xerrors.WithStackTrace(xerrors.Join(err, lastErr))
618619
}
619620

620-
item, waitFromChErr := p.waitFromCh(ctx)
621+
lastErr = err
622+
623+
item, err = p.waitFromCh(ctx)
621624
if item != nil {
622625
return item, nil
623626
}
624627

625-
if waitFromChErr != nil && !isRetriable(waitFromChErr) {
626-
return nil, xerrors.WithStackTrace(waitFromChErr)
628+
if err != nil && !isRetriable(err) {
629+
return nil, xerrors.WithStackTrace(xerrors.Join(err, lastErr))
627630
}
628631

629-
lastErr = xerrors.WithStackTrace(xerrors.Join(createItemErr, waitFromChErr))
632+
lastErr = err
630633
}
631634

632635
p.mu.RLock()

internal/table/retry_test.go

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -132,26 +132,29 @@ func TestDoBadSession(t *testing.T) {
132132
}
133133

134134
func TestDoCreateSessionError(t *testing.T) {
135-
ctx, cancel := xcontext.WithTimeout(xtest.Context(t), time.Second)
136-
defer cancel()
137-
p := pool.New[*session, session](ctx,
138-
pool.WithCreateItemFunc[*session, session](func(ctx context.Context) (*session, error) {
139-
return nil, xerrors.Operation(xerrors.WithStatusCode(Ydb.StatusIds_UNAVAILABLE))
140-
}),
141-
pool.WithSyncCloseItem[*session, session](),
142-
)
143-
err := do(ctx, p, config.New(),
144-
func(ctx context.Context, s table.Session) error {
145-
return nil
146-
},
147-
nil,
148-
)
149-
if !xerrors.Is(err, context.DeadlineExceeded) {
150-
t.Errorf("unexpected error: %v", err)
151-
}
152-
if !xerrors.IsOperationError(err, Ydb.StatusIds_UNAVAILABLE) {
153-
t.Errorf("unexpected error: %v", err)
154-
}
135+
rootCtx := xtest.Context(t)
136+
xtest.TestManyTimes(t, func(t testing.TB) {
137+
ctx, cancel := xcontext.WithTimeout(rootCtx, 30*time.Millisecond)
138+
defer cancel()
139+
p := pool.New[*session, session](ctx,
140+
pool.WithCreateItemFunc[*session, session](func(ctx context.Context) (*session, error) {
141+
return nil, xerrors.Operation(xerrors.WithStatusCode(Ydb.StatusIds_UNAVAILABLE))
142+
}),
143+
pool.WithSyncCloseItem[*session, session](),
144+
)
145+
err := do(ctx, p, config.New(),
146+
func(ctx context.Context, s table.Session) error {
147+
return nil
148+
},
149+
nil,
150+
)
151+
if !xerrors.Is(err, context.DeadlineExceeded) {
152+
t.Errorf("unexpected error: %v", err)
153+
}
154+
if !xerrors.IsOperationError(err, Ydb.StatusIds_UNAVAILABLE) {
155+
t.Errorf("unexpected error: %v", err)
156+
}
157+
})
155158
}
156159

157160
func TestDoImmediateReturn(t *testing.T) {

retry/retry.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ func RetryWithResult[T any](ctx context.Context, //nolint:revive,funlen
319319
var (
320320
i int
321321
attempts int
322+
lastErr error
322323

323324
code = int64(0)
324325
onDone = trace.RetryOnRetry(options.trace, &ctx,
@@ -333,9 +334,10 @@ func RetryWithResult[T any](ctx context.Context, //nolint:revive,funlen
333334
attempts++
334335
select {
335336
case <-ctx.Done():
336-
return zeroValue, xerrors.WithStackTrace(
337+
return zeroValue, xerrors.WithStackTrace(xerrors.Join(
337338
fmt.Errorf("retry failed on attempt No.%d: %w", attempts, ctx.Err()),
338-
)
339+
lastErr,
340+
))
339341

340342
default:
341343
v, err := opWithRecover(ctx, options, op)
@@ -353,10 +355,11 @@ func RetryWithResult[T any](ctx context.Context, //nolint:revive,funlen
353355
code = m.StatusCode()
354356

355357
if !m.MustRetry(options.idempotent) {
356-
return zeroValue, xerrors.WithStackTrace(
358+
return zeroValue, xerrors.WithStackTrace(xerrors.Join(
357359
fmt.Errorf("non-retryable error occurred on attempt No.%d (idempotent=%v): %w",
358360
attempts, options.idempotent, err),
359-
)
361+
lastErr,
362+
))
360363
}
361364

362365
t := time.NewTimer(backoff.Delay(m.BackoffType(), i,
@@ -372,6 +375,7 @@ func RetryWithResult[T any](ctx context.Context, //nolint:revive,funlen
372375
xerrors.Join(
373376
fmt.Errorf("attempt No.%d: %w", attempts, ctx.Err()),
374377
err,
378+
lastErr,
375379
),
376380
)
377381
case <-t.C:
@@ -383,10 +387,13 @@ func RetryWithResult[T any](ctx context.Context, //nolint:revive,funlen
383387
fmt.Errorf("attempt No.%d: %w", attempts, budget.ErrNoQuota),
384388
acquireErr,
385389
err,
390+
lastErr,
386391
),
387392
)
388393
}
389394
}
395+
396+
lastErr = err
390397
}
391398
}
392399
}

0 commit comments

Comments
 (0)