/
githubmirror
/
ydb-go-sdk
Обзор
Документация
Войти
/
githubmirror
/
ydb-go-sdk
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
retry/errors_data_test.go
458 строк
10 KB
Aleksey Myasnikov
Changed the retry behavior for operation error `TIMEOUT` from `NonRetryable` to `ConditionallyRetryable` (#2153)
13 май 2026, 00:15
Не верифицирован
13 май 2026, 00:15
20ae4ec
Код
Авторство
О чём код?
package retry import ( "context" "fmt" "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Issue" "google.golang.org/grpc" grpcCodes "google.golang.org/grpc/codes" grpcStatus "google.golang.org/grpc/status" "github.com/ydb-platform/ydb-go-sdk/v3/internal/backoff" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) type idempotency bool func (t idempotency) String() string { if t { return "idempotent" } return "non-idempotent" } const ( idempotent = true nonIdempotent = false ) var errsToCheck = []struct { err error // given error backoff backoff.Type // no backoff (=== no operationStatus), fast backoff, slow backoff canRetry map[idempotency]bool }{ { // retryer given unknown error - we will not operationStatus and will close session err: fmt.Errorf("unknown error"), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { // golang context deadline exceeded err: context.DeadlineExceeded, backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { // golang context canceled err: context.Canceled, backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport( //nolint:staticcheck // ignore SA1019 //nolint:nolintlint grpc.ErrClientConnClosing, ), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.Canceled, "")), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: true, // if client context is not done nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unknown, "")), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.InvalidArgument, "")), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.DeadlineExceeded, "")), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: true, // if client context is not done nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.NotFound, "")), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.AlreadyExists, "")), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.PermissionDenied, "")), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.ResourceExhausted, "")), backoff: backoff.TypeSlow, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: true, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.ResourceExhausted, "trying to send message larger than max (70792102 vs. 64000000)")), //nolint:lll backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.ResourceExhausted, "received message larger than max (70792102 vs. 64000000)")), //nolint:lll backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.FailedPrecondition, "")), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.Aborted, "")), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: true, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.OutOfRange, "")), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unimplemented, "")), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.Internal, "")), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unavailable, "")), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: false, }, }, { err: xerrors.Retryable( xerrors.Transport(grpcStatus.Error(grpcCodes.Unavailable, "")), xerrors.WithBackoff(backoff.TypeFast), ), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: true, }, }, { err: xerrors.Retryable( grpcStatus.Error(grpcCodes.Unavailable, ""), xerrors.WithBackoff(backoff.TypeFast), ), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: true, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.DataLoss, "")), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unauthenticated, "")), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_STATUS_CODE_UNSPECIFIED), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_BAD_REQUEST), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_UNAUTHORIZED), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_INTERNAL_ERROR), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_EXTERNAL_ERROR), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_ABORTED), ), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: true, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_ABORTED), xerrors.WithIssues([]*Ydb_Issue.IssueMessage{ { IssueCode: xerrors.IssueCodeDatashardProgramSizeLimitExceeded, }, }), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_UNAVAILABLE), ), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: true, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_OVERLOADED), ), backoff: backoff.TypeSlow, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: true, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_SCHEME_ERROR), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_GENERIC_ERROR), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_TIMEOUT), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_BAD_SESSION), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: true, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_PRECONDITION_FAILED), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_ALREADY_EXISTS), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_NOT_FOUND), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_SESSION_EXPIRED), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_CANCELLED), ), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_UNDETERMINED), ), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_UNSUPPORTED), ), backoff: backoff.TypeInstant, canRetry: map[idempotency]bool{ idempotent: false, nonIdempotent: false, }, }, { err: xerrors.Operation( xerrors.WithStatusCode(Ydb.StatusIds_SESSION_BUSY), ), backoff: backoff.TypeFast, canRetry: map[idempotency]bool{ idempotent: true, nonIdempotent: true, }, }, }