@@ -17,6 +17,8 @@ const (
1717 connectionEstablishedTimeout = time .Minute
1818)
1919
20+ var errNil = xerrors .Wrap (errors .New ("nil error is not retrieable" ))
21+
2022type RetrySettings struct {
2123 StartTimeout time.Duration // Full retry timeout
2224 CheckError PublicCheckErrorRetryFunction
@@ -53,50 +55,58 @@ func CheckResetReconnectionCounters(lastTry, now time.Time, connectionTimeout ti
5355 return now .Sub (lastTry ) > connectionTimeout * resetAttemptEmpiricalCoefficient
5456}
5557
56- func CheckRetryMode (err error , settings RetrySettings , retriesDuration time.Duration ) (
58+ // RetryDecision check if err is retriable.
59+ // if return nil stopRetryReason - err can be retried
60+ // if return non nil stopRetryReason - err is not retriable and stopRetryReason contains reason,
61+ // which should be used instead of err
62+ func RetryDecision (checkErr error , settings RetrySettings , retriesDuration time.Duration ) (
5763 _ backoff.Backoff ,
58- isRetriable bool ,
64+ stopRetryReason error ,
5965) {
6066 // nil is not error and doesn't need retry it.
61- if err == nil {
62- return nil , false
67+ if checkErr == nil {
68+ return nil , xerrors . WithStackTrace ( errNil )
6369 }
6470
6571 // eof is retriable for topic
66- if errors .Is (err , io .EOF ) && xerrors .RetryableError (err ) == nil {
67- err = xerrors .Retryable (err , xerrors .WithName ("TopicEOF" ))
72+ if errors .Is (checkErr , io .EOF ) && xerrors .RetryableError (checkErr ) == nil {
73+ checkErr = xerrors .Retryable (checkErr , xerrors .WithName ("TopicEOF" ))
6874 }
6975
7076 if retriesDuration > settings .StartTimeout {
71- return nil , false
77+ return nil , fmt . Errorf ( "ydb: topic reader reconnection timeout, last error: %w" , xerrors . Unretryable ( checkErr ))
7278 }
7379
74- mode := retry .Check (err )
80+ mode := retry .Check (checkErr )
7581
7682 decision := PublicRetryDecisionDefault
7783 if settings .CheckError != nil {
78- decision = settings .CheckError (NewCheckRetryArgs (err ))
84+ decision = settings .CheckError (NewCheckRetryArgs (checkErr ))
7985 }
8086
8187 switch decision {
8288 case PublicRetryDecisionDefault :
83- isRetriable = mode .MustRetry (true )
89+ isRetriable := mode .MustRetry (true )
90+ if ! isRetriable {
91+ return nil , fmt .Errorf ("ydb: topic reader unretriable error: %w" , xerrors .Unretryable (checkErr ))
92+ }
8493 case PublicRetryDecisionRetry :
85- isRetriable = true
94+ // pass
8695 case PublicRetryDecisionStop :
87- isRetriable = false
96+ return nil , fmt .Errorf (
97+ "ydb: topic reader unretriable error by check error callback: %w" ,
98+ xerrors .Unretryable (checkErr ),
99+ )
88100 default :
89101 panic (fmt .Errorf ("unexpected retry decision: %v" , decision ))
90102 }
91103
92- if ! isRetriable {
93- return nil , false
94- }
104+ // checkErr is retryable error
95105
96106 switch mode .BackoffType () {
97107 case backoff .TypeFast :
98- return backoff .Fast , true
108+ return backoff .Fast , nil
99109 default :
100- return backoff .Slow , true
110+ return backoff .Slow , nil
101111 }
102112}
0 commit comments