github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/retry/errors_data_test.go (about)

     1  package retry
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
     8  	"google.golang.org/grpc"
     9  	grpcCodes "google.golang.org/grpc/codes"
    10  	grpcStatus "google.golang.org/grpc/status"
    11  
    12  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/backoff"
    13  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
    14  )
    15  
    16  type idempotency bool
    17  
    18  func (t idempotency) String() string {
    19  	if t {
    20  		return "idempotent"
    21  	}
    22  
    23  	return "non-idempotent"
    24  }
    25  
    26  const (
    27  	idempotent    = true
    28  	nonIdempotent = false
    29  )
    30  
    31  var errsToCheck = []struct {
    32  	err           error        // given error
    33  	backoff       backoff.Type // no backoff (=== no operationStatus), fast backoff, slow backoff
    34  	deleteSession bool         // close session and delete from pool
    35  	canRetry      map[idempotency]bool
    36  }{
    37  	{
    38  		// retryer given unknown error - we will not operationStatus and will close session
    39  		err:           fmt.Errorf("unknown error"),
    40  		backoff:       backoff.TypeNoBackoff,
    41  		deleteSession: false,
    42  		canRetry: map[idempotency]bool{
    43  			idempotent:    false,
    44  			nonIdempotent: false,
    45  		},
    46  	},
    47  	{
    48  		// golang context deadline exceeded
    49  		err:           context.DeadlineExceeded,
    50  		backoff:       backoff.TypeNoBackoff,
    51  		deleteSession: false,
    52  		canRetry: map[idempotency]bool{
    53  			idempotent:    false,
    54  			nonIdempotent: false,
    55  		},
    56  	},
    57  	{
    58  		// golang context canceled
    59  		err:           context.Canceled,
    60  		backoff:       backoff.TypeNoBackoff,
    61  		deleteSession: false,
    62  		canRetry: map[idempotency]bool{
    63  			idempotent:    false,
    64  			nonIdempotent: false,
    65  		},
    66  	},
    67  	{
    68  		err: xerrors.Transport(
    69  			//nolint:staticcheck
    70  			// ignore SA1019
    71  			//nolint:nolintlint
    72  			grpc.ErrClientConnClosing,
    73  		),
    74  		backoff:       backoff.TypeFast,
    75  		deleteSession: true,
    76  		canRetry: map[idempotency]bool{
    77  			idempotent:    true,
    78  			nonIdempotent: false,
    79  		},
    80  	},
    81  	{
    82  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.Canceled, "")),
    83  		backoff:       backoff.TypeFast,
    84  		deleteSession: true,
    85  		canRetry: map[idempotency]bool{
    86  			idempotent:    true, // if client context is not done
    87  			nonIdempotent: false,
    88  		},
    89  	},
    90  	{
    91  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.Unknown, "")),
    92  		backoff:       backoff.TypeNoBackoff,
    93  		deleteSession: true,
    94  		canRetry: map[idempotency]bool{
    95  			idempotent:    false,
    96  			nonIdempotent: false,
    97  		},
    98  	},
    99  	{
   100  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.InvalidArgument, "")),
   101  		backoff:       backoff.TypeNoBackoff,
   102  		deleteSession: true,
   103  		canRetry: map[idempotency]bool{
   104  			idempotent:    false,
   105  			nonIdempotent: false,
   106  		},
   107  	},
   108  	{
   109  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.DeadlineExceeded, "")),
   110  		backoff:       backoff.TypeFast,
   111  		deleteSession: true,
   112  		canRetry: map[idempotency]bool{
   113  			idempotent:    true, // if client context is not done
   114  			nonIdempotent: false,
   115  		},
   116  	},
   117  	{
   118  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.NotFound, "")),
   119  		backoff:       backoff.TypeNoBackoff,
   120  		deleteSession: true,
   121  		canRetry: map[idempotency]bool{
   122  			idempotent:    false,
   123  			nonIdempotent: false,
   124  		},
   125  	},
   126  	{
   127  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.AlreadyExists, "")),
   128  		backoff:       backoff.TypeNoBackoff,
   129  		deleteSession: true,
   130  		canRetry: map[idempotency]bool{
   131  			idempotent:    false,
   132  			nonIdempotent: false,
   133  		},
   134  	},
   135  	{
   136  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.PermissionDenied, "")),
   137  		backoff:       backoff.TypeNoBackoff,
   138  		deleteSession: true,
   139  		canRetry: map[idempotency]bool{
   140  			idempotent:    false,
   141  			nonIdempotent: false,
   142  		},
   143  	},
   144  	{
   145  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.ResourceExhausted, "")),
   146  		backoff:       backoff.TypeSlow,
   147  		deleteSession: false,
   148  		canRetry: map[idempotency]bool{
   149  			idempotent:    true,
   150  			nonIdempotent: true,
   151  		},
   152  	},
   153  	{
   154  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.FailedPrecondition, "")),
   155  		backoff:       backoff.TypeNoBackoff,
   156  		deleteSession: true,
   157  		canRetry: map[idempotency]bool{
   158  			idempotent:    false,
   159  			nonIdempotent: false,
   160  		},
   161  	},
   162  	{
   163  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.Aborted, "")),
   164  		backoff:       backoff.TypeNoBackoff,
   165  		deleteSession: true,
   166  		canRetry: map[idempotency]bool{
   167  			idempotent:    true,
   168  			nonIdempotent: true,
   169  		},
   170  	},
   171  	{
   172  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.OutOfRange, "")),
   173  		backoff:       backoff.TypeNoBackoff,
   174  		deleteSession: false,
   175  		canRetry: map[idempotency]bool{
   176  			idempotent:    false,
   177  			nonIdempotent: false,
   178  		},
   179  	},
   180  	{
   181  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.Unimplemented, "")),
   182  		backoff:       backoff.TypeNoBackoff,
   183  		deleteSession: true,
   184  		canRetry: map[idempotency]bool{
   185  			idempotent:    false,
   186  			nonIdempotent: false,
   187  		},
   188  	},
   189  	{
   190  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.Internal, "")),
   191  		backoff:       backoff.TypeFast,
   192  		deleteSession: true,
   193  		canRetry: map[idempotency]bool{
   194  			idempotent:    true,
   195  			nonIdempotent: false,
   196  		},
   197  	},
   198  	{
   199  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.Unavailable, "")),
   200  		backoff:       backoff.TypeFast,
   201  		deleteSession: true,
   202  		canRetry: map[idempotency]bool{
   203  			idempotent:    true,
   204  			nonIdempotent: false,
   205  		},
   206  	},
   207  	{
   208  		err: xerrors.Retryable(
   209  			xerrors.Transport(grpcStatus.Error(grpcCodes.Unavailable, "")),
   210  			xerrors.WithBackoff(backoff.TypeFast),
   211  			xerrors.WithDeleteSession(),
   212  		),
   213  		backoff:       backoff.TypeFast,
   214  		deleteSession: true,
   215  		canRetry: map[idempotency]bool{
   216  			idempotent:    true,
   217  			nonIdempotent: true,
   218  		},
   219  	},
   220  	{
   221  		err: xerrors.Retryable(
   222  			grpcStatus.Error(grpcCodes.Unavailable, ""),
   223  			xerrors.WithBackoff(backoff.TypeFast),
   224  			xerrors.WithDeleteSession(),
   225  		),
   226  		backoff:       backoff.TypeFast,
   227  		deleteSession: true,
   228  		canRetry: map[idempotency]bool{
   229  			idempotent:    true,
   230  			nonIdempotent: true,
   231  		},
   232  	},
   233  	{
   234  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.DataLoss, "")),
   235  		backoff:       backoff.TypeNoBackoff,
   236  		deleteSession: true,
   237  		canRetry: map[idempotency]bool{
   238  			idempotent:    false,
   239  			nonIdempotent: false,
   240  		},
   241  	},
   242  	{
   243  		err:           xerrors.Transport(grpcStatus.Error(grpcCodes.Unauthenticated, "")),
   244  		backoff:       backoff.TypeNoBackoff,
   245  		deleteSession: true,
   246  		canRetry: map[idempotency]bool{
   247  			idempotent:    false,
   248  			nonIdempotent: false,
   249  		},
   250  	},
   251  	{
   252  		err: xerrors.Operation(
   253  			xerrors.WithStatusCode(Ydb.StatusIds_STATUS_CODE_UNSPECIFIED),
   254  		),
   255  		backoff:       backoff.TypeNoBackoff,
   256  		deleteSession: false,
   257  		canRetry: map[idempotency]bool{
   258  			idempotent:    false,
   259  			nonIdempotent: false,
   260  		},
   261  	},
   262  	{
   263  		err: xerrors.Operation(
   264  			xerrors.WithStatusCode(Ydb.StatusIds_BAD_REQUEST),
   265  		),
   266  		backoff:       backoff.TypeNoBackoff,
   267  		deleteSession: false,
   268  		canRetry: map[idempotency]bool{
   269  			idempotent:    false,
   270  			nonIdempotent: false,
   271  		},
   272  	},
   273  	{
   274  		err: xerrors.Operation(
   275  			xerrors.WithStatusCode(Ydb.StatusIds_UNAUTHORIZED),
   276  		),
   277  		backoff:       backoff.TypeNoBackoff,
   278  		deleteSession: false,
   279  		canRetry: map[idempotency]bool{
   280  			idempotent:    false,
   281  			nonIdempotent: false,
   282  		},
   283  	},
   284  	{
   285  		err: xerrors.Operation(
   286  			xerrors.WithStatusCode(Ydb.StatusIds_INTERNAL_ERROR),
   287  		),
   288  		backoff:       backoff.TypeNoBackoff,
   289  		deleteSession: false,
   290  		canRetry: map[idempotency]bool{
   291  			idempotent:    false,
   292  			nonIdempotent: false,
   293  		},
   294  	},
   295  	{
   296  		err: xerrors.Operation(
   297  			xerrors.WithStatusCode(Ydb.StatusIds_ABORTED),
   298  		),
   299  		backoff:       backoff.TypeFast,
   300  		deleteSession: false,
   301  		canRetry: map[idempotency]bool{
   302  			idempotent:    true,
   303  			nonIdempotent: true,
   304  		},
   305  	},
   306  	{
   307  		err: xerrors.Operation(
   308  			xerrors.WithStatusCode(Ydb.StatusIds_UNAVAILABLE),
   309  		),
   310  		backoff:       backoff.TypeFast,
   311  		deleteSession: false,
   312  		canRetry: map[idempotency]bool{
   313  			idempotent:    true,
   314  			nonIdempotent: true,
   315  		},
   316  	},
   317  	{
   318  		err: xerrors.Operation(
   319  			xerrors.WithStatusCode(Ydb.StatusIds_OVERLOADED),
   320  		),
   321  		backoff:       backoff.TypeSlow,
   322  		deleteSession: false,
   323  		canRetry: map[idempotency]bool{
   324  			idempotent:    true,
   325  			nonIdempotent: true,
   326  		},
   327  	},
   328  	{
   329  		err: xerrors.Operation(
   330  			xerrors.WithStatusCode(Ydb.StatusIds_SCHEME_ERROR),
   331  		),
   332  		backoff:       backoff.TypeNoBackoff,
   333  		deleteSession: false,
   334  		canRetry: map[idempotency]bool{
   335  			idempotent:    false,
   336  			nonIdempotent: false,
   337  		},
   338  	},
   339  	{
   340  		err: xerrors.Operation(
   341  			xerrors.WithStatusCode(Ydb.StatusIds_GENERIC_ERROR),
   342  		),
   343  		backoff:       backoff.TypeNoBackoff,
   344  		deleteSession: false,
   345  		canRetry: map[idempotency]bool{
   346  			idempotent:    false,
   347  			nonIdempotent: false,
   348  		},
   349  	},
   350  	{
   351  		err: xerrors.Operation(
   352  			xerrors.WithStatusCode(Ydb.StatusIds_TIMEOUT),
   353  		),
   354  		backoff:       backoff.TypeNoBackoff,
   355  		deleteSession: false,
   356  		canRetry: map[idempotency]bool{
   357  			idempotent:    false,
   358  			nonIdempotent: false,
   359  		},
   360  	},
   361  	{
   362  		err: xerrors.Operation(
   363  			xerrors.WithStatusCode(Ydb.StatusIds_BAD_SESSION),
   364  		),
   365  		backoff:       backoff.TypeNoBackoff,
   366  		deleteSession: true,
   367  		canRetry: map[idempotency]bool{
   368  			idempotent:    true,
   369  			nonIdempotent: true,
   370  		},
   371  	},
   372  	{
   373  		err: xerrors.Operation(
   374  			xerrors.WithStatusCode(Ydb.StatusIds_PRECONDITION_FAILED),
   375  		),
   376  		backoff:       backoff.TypeNoBackoff,
   377  		deleteSession: false,
   378  		canRetry: map[idempotency]bool{
   379  			idempotent:    false,
   380  			nonIdempotent: false,
   381  		},
   382  	},
   383  	{
   384  		err: xerrors.Operation(
   385  			xerrors.WithStatusCode(Ydb.StatusIds_ALREADY_EXISTS),
   386  		),
   387  		backoff:       backoff.TypeNoBackoff,
   388  		deleteSession: false,
   389  		canRetry: map[idempotency]bool{
   390  			idempotent:    false,
   391  			nonIdempotent: false,
   392  		},
   393  	},
   394  	{
   395  		err: xerrors.Operation(
   396  			xerrors.WithStatusCode(Ydb.StatusIds_NOT_FOUND),
   397  		),
   398  		backoff:       backoff.TypeNoBackoff,
   399  		deleteSession: false,
   400  		canRetry: map[idempotency]bool{
   401  			idempotent:    false,
   402  			nonIdempotent: false,
   403  		},
   404  	},
   405  	{
   406  		err: xerrors.Operation(
   407  			xerrors.WithStatusCode(Ydb.StatusIds_SESSION_EXPIRED),
   408  		),
   409  		backoff:       backoff.TypeNoBackoff,
   410  		deleteSession: true,
   411  		canRetry: map[idempotency]bool{
   412  			idempotent:    true,
   413  			nonIdempotent: false,
   414  		},
   415  	},
   416  	{
   417  		err: xerrors.Operation(
   418  			xerrors.WithStatusCode(Ydb.StatusIds_CANCELLED),
   419  		),
   420  		backoff:       backoff.TypeFast,
   421  		deleteSession: false,
   422  		canRetry: map[idempotency]bool{
   423  			idempotent:    false,
   424  			nonIdempotent: false,
   425  		},
   426  	},
   427  	{
   428  		err: xerrors.Operation(
   429  			xerrors.WithStatusCode(Ydb.StatusIds_UNDETERMINED),
   430  		),
   431  		backoff:       backoff.TypeFast,
   432  		deleteSession: false,
   433  		canRetry: map[idempotency]bool{
   434  			idempotent:    true,
   435  			nonIdempotent: false,
   436  		},
   437  	},
   438  	{
   439  		err: xerrors.Operation(
   440  			xerrors.WithStatusCode(Ydb.StatusIds_UNSUPPORTED),
   441  		),
   442  		backoff:       backoff.TypeNoBackoff,
   443  		deleteSession: false,
   444  		canRetry: map[idempotency]bool{
   445  			idempotent:    false,
   446  			nonIdempotent: false,
   447  		},
   448  	},
   449  	{
   450  		err: xerrors.Operation(
   451  			xerrors.WithStatusCode(Ydb.StatusIds_SESSION_BUSY),
   452  		),
   453  		backoff:       backoff.TypeFast,
   454  		deleteSession: true,
   455  		canRetry: map[idempotency]bool{
   456  			idempotent:    true,
   457  			nonIdempotent: true,
   458  		},
   459  	},
   460  }