github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/internal/topic/retriable_error.go (about) 1 package topic 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "time" 8 9 "github.com/ydb-platform/ydb-go-sdk/v3/internal/backoff" 10 "github.com/ydb-platform/ydb-go-sdk/v3/internal/value" 11 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" 12 "github.com/ydb-platform/ydb-go-sdk/v3/retry" 13 ) 14 15 const ( 16 DefaultStartTimeout = time.Minute 17 connectionEstablishedTimeout = time.Minute 18 ) 19 20 type RetrySettings struct { 21 StartTimeout time.Duration // Full retry timeout 22 CheckError PublicCheckErrorRetryFunction 23 } 24 25 type PublicCheckErrorRetryFunction func(errInfo PublicCheckErrorRetryArgs) PublicCheckRetryResult 26 27 type PublicCheckErrorRetryArgs struct { 28 Error error 29 } 30 31 func NewCheckRetryArgs(err error) PublicCheckErrorRetryArgs { 32 return PublicCheckErrorRetryArgs{ 33 Error: err, 34 } 35 } 36 37 type PublicCheckRetryResult struct { 38 val int 39 } 40 41 var ( 42 PublicRetryDecisionDefault = PublicCheckRetryResult{val: 0} 43 PublicRetryDecisionRetry = PublicCheckRetryResult{val: 1} 44 PublicRetryDecisionStop = PublicCheckRetryResult{val: 2} 45 ) 46 47 func CheckResetReconnectionCounters(lastTry, now time.Time, connectionTimeout time.Duration) bool { 48 const resetAttemptEmpiricalCoefficient = 10 49 if connectionTimeout == value.InfiniteDuration { 50 return now.Sub(lastTry) > connectionEstablishedTimeout 51 } 52 53 return now.Sub(lastTry) > connectionTimeout*resetAttemptEmpiricalCoefficient 54 } 55 56 func CheckRetryMode(err error, settings RetrySettings, retriesDuration time.Duration) ( 57 _ backoff.Backoff, 58 isRetriable bool, 59 ) { 60 // nil is not error and doesn't need retry it. 61 if err == nil { 62 return nil, false 63 } 64 65 // eof is retriable for topic 66 if errors.Is(err, io.EOF) && xerrors.RetryableError(err) == nil { 67 err = xerrors.Retryable(err, xerrors.WithName("TopicEOF")) 68 } 69 70 if retriesDuration > settings.StartTimeout { 71 return nil, false 72 } 73 74 mode := retry.Check(err) 75 76 decision := PublicRetryDecisionDefault 77 if settings.CheckError != nil { 78 decision = settings.CheckError(NewCheckRetryArgs(err)) 79 } 80 81 switch decision { 82 case PublicRetryDecisionDefault: 83 isRetriable = mode.MustRetry(true) 84 case PublicRetryDecisionRetry: 85 isRetriable = true 86 case PublicRetryDecisionStop: 87 isRetriable = false 88 default: 89 panic(fmt.Errorf("unexpected retry decision: %v", decision)) 90 } 91 92 if !isRetriable { 93 return nil, false 94 } 95 96 switch mode.BackoffType() { 97 case backoff.TypeFast: 98 return backoff.Fast, true 99 default: 100 return backoff.Slow, true 101 } 102 }