Skip to content

Commit 4de228d

Browse files
committed
Added retry.Invalid method for mark as invalid concrete object
1 parent f541a53 commit 4de228d

File tree

19 files changed

+140
-50
lines changed

19 files changed

+140
-50
lines changed

internal/pool/pool_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ func TestPool(t *testing.T) { //nolint:gocyclo
849849
var (
850850
newItems atomic.Int64
851851
deleteItems atomic.Int64
852-
expErr = xerrors.Retryable(errors.New("expected error"), xerrors.InvalidObject())
852+
expErr = errors.New("expected error")
853853
)
854854
p := New(rootCtx,
855855
WithLimit[*testItem, testItem](1),
@@ -874,7 +874,7 @@ func TestPool(t *testing.T) { //nolint:gocyclo
874874
)
875875
err := p.With(rootCtx, func(ctx context.Context, testItem *testItem) error {
876876
if newItems.Load() < 10 {
877-
return expErr
877+
return xerrors.Retryable(expErr, xerrors.Invalid(testItem))
878878
}
879879

880880
return nil

internal/xerrors/retryable.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type retryableError struct {
1414
backoffType backoff.Type
1515
code int32
1616
traceID string
17+
invalidObjs []any
1718
}
1819

1920
func (re *retryableError) Code() int32 {
@@ -81,18 +82,27 @@ func WithName(name string) nameOption {
8182
return nameOption(name)
8283
}
8384

84-
type invalidObjectOption struct{}
85+
type invalidObjectOption struct {
86+
obj any
87+
}
8588

86-
func (invalidObjectOption) applyToRetryableError(re *retryableError) {
89+
func (opt invalidObjectOption) applyToRetryableError(re *retryableError) {
90+
re.invalidObjs = append(re.invalidObjs, opt.obj)
8791
}
8892

8993
// InvalidObject deprecated option
9094
//
91-
// Deprecated
95+
// Deprecated: use Invalid instead
9296
func InvalidObject() invalidObjectOption {
9397
return invalidObjectOption{}
9498
}
9599

100+
func Invalid(obj any) invalidObjectOption {
101+
return invalidObjectOption{
102+
obj: obj,
103+
}
104+
}
105+
96106
func Retryable(err error, opts ...RetryableErrorOption) error {
97107
if err == nil {
98108
return nil
@@ -158,3 +168,22 @@ func IsRetryableError(err error) bool {
158168

159169
return false
160170
}
171+
172+
func IsValid[T comparable](err error, obj T) bool {
173+
if err == nil {
174+
return true
175+
}
176+
177+
var e *retryableError
178+
if !errors.As(err, &e) {
179+
return true
180+
}
181+
182+
for _, o := range e.invalidObjs {
183+
if invalidObj, has := o.(T); has && invalidObj == obj {
184+
return false
185+
}
186+
}
187+
188+
return true
189+
}

internal/xerrors/retryable_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,16 @@ func TestUnretryableUnwrap(t *testing.T) {
7171
wrapped := Unretryable(test)
7272
require.ErrorIs(t, wrapped, test)
7373
}
74+
75+
func TestIsValid(t *testing.T) {
76+
type myType struct{}
77+
obj := &myType{}
78+
err := Retryable(fmt.Errorf("test"), Invalid(obj))
79+
require.False(t, IsValid(err, obj))
80+
require.True(t, IsValid(err, &myType{}))
81+
var objAsInterface any
82+
objAsInterface = obj
83+
require.False(t, IsValid(err, objAsInterface))
84+
objAsInterface = &myType{}
85+
require.True(t, IsValid(err, objAsInterface))
86+
}

internal/xerrors/session_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,10 @@ func TestMustDeleteTableOrQuerySession(t *testing.T) {
3838
Retryable(
3939
Transport(grpcStatus.Error(grpcCodes.Unavailable, "")),
4040
WithBackoff(backoff.TypeFast),
41-
InvalidObject(),
4241
),
4342
Retryable(
4443
grpcStatus.Error(grpcCodes.Unavailable, ""),
4544
WithBackoff(backoff.TypeFast),
46-
InvalidObject(),
4745
),
4846
Transport(grpcStatus.Error(grpcCodes.DataLoss, "")),
4947
Transport(grpcStatus.Error(grpcCodes.Unauthenticated, "")),

internal/xsql/conn.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,10 @@ func (c *Conn) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, f
118118
}()
119119

120120
if !c.cc.IsValid() {
121-
return nil, xerrors.WithStackTrace(errNotReadyConn)
121+
return nil, xerrors.WithStackTrace(xerrors.Retryable(errNotReadyConn,
122+
xerrors.Invalid(c),
123+
xerrors.Invalid(c.cc),
124+
))
122125
}
123126

124127
return &Stmt{

internal/xsql/errors.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ package xsql
33
import (
44
"database/sql/driver"
55
"errors"
6-
7-
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
86
)
97

108
var (
119
ErrUnsupported = driver.ErrSkip
1210
errDeprecated = driver.ErrSkip
1311
errWrongQueryProcessor = errors.New("wrong query processor")
14-
errNotReadyConn = xerrors.Retryable(errors.New("conn not ready"), xerrors.InvalidObject())
12+
errNotReadyConn = errors.New("conn not ready")
1513
)

internal/xsql/stmt.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ func (stmt *Stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_
3636
}()
3737

3838
if !stmt.conn.cc.IsValid() {
39-
return nil, xerrors.WithStackTrace(errNotReadyConn)
39+
return nil, xerrors.WithStackTrace(xerrors.Retryable(errNotReadyConn,
40+
xerrors.Invalid(stmt),
41+
xerrors.Invalid(stmt.conn),
42+
xerrors.Invalid(stmt.conn.cc),
43+
))
4044
}
4145

4246
sql, params, err := stmt.conn.toYdb(stmt.sql, args...)
@@ -57,7 +61,11 @@ func (stmt *Stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_
5761
}()
5862

5963
if !stmt.conn.cc.IsValid() {
60-
return nil, xerrors.WithStackTrace(errNotReadyConn)
64+
return nil, xerrors.WithStackTrace(xerrors.Retryable(errNotReadyConn,
65+
xerrors.Invalid(stmt),
66+
xerrors.Invalid(stmt.conn),
67+
xerrors.Invalid(stmt.conn.cc),
68+
))
6169
}
6270

6371
sql, params, err := stmt.conn.toYdb(stmt.sql, args...)

internal/xsql/tx.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,11 @@ func (tx *Tx) PrepareContext(ctx context.Context, sql string) (_ driver.Stmt, fi
144144
onDone(finalErr)
145145
}()
146146
if !tx.conn.cc.IsValid() {
147-
return nil, badconn.Map(xerrors.WithStackTrace(errNotReadyConn))
147+
return nil, badconn.Map(xerrors.WithStackTrace(xerrors.Retryable(errNotReadyConn,
148+
xerrors.Invalid(tx),
149+
xerrors.Invalid(tx.conn),
150+
xerrors.Invalid(tx.conn.cc),
151+
)))
148152
}
149153

150154
return &Stmt{

internal/xsql/xquery/conn.go

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,17 @@ func (c *Conn) Exec(ctx context.Context, sql string, params *params.Params) (
4343
result driver.Result, finalErr error,
4444
) {
4545
if !c.IsValid() {
46-
return nil, xerrors.WithStackTrace(errNotReadyConn)
46+
return nil, xerrors.WithStackTrace(xerrors.Retryable(errNotReadyConn,
47+
xerrors.Invalid(c),
48+
xerrors.Invalid(c.session),
49+
))
4750
}
4851

4952
if !c.isReady() {
50-
return nil, xerrors.WithStackTrace(errNotReadyConn)
53+
return nil, xerrors.WithStackTrace(xerrors.Retryable(errNotReadyConn,
54+
xerrors.Invalid(c),
55+
xerrors.Invalid(c.session),
56+
))
5157
}
5258

5359
opts := []options.Execute{
@@ -70,11 +76,10 @@ func (c *Conn) Query(ctx context.Context, sql string, params *params.Params) (
7076
result driver.RowsNextResultSet, finalErr error,
7177
) {
7278
if !c.isReady() {
73-
return nil, xerrors.WithStackTrace(errNotReadyConn)
74-
}
75-
76-
if !c.isReady() {
77-
return nil, xerrors.WithStackTrace(errNotReadyConn)
79+
return nil, xerrors.WithStackTrace(xerrors.Retryable(errNotReadyConn,
80+
xerrors.Invalid(c),
81+
xerrors.Invalid(c.session),
82+
))
7883
}
7984

8085
opts := []options.Execute{
@@ -155,11 +160,17 @@ func (c *Conn) IsValid() bool {
155160

156161
func (c *Conn) Ping(ctx context.Context) (finalErr error) {
157162
if !c.isReady() {
158-
return xerrors.WithStackTrace(errNotReadyConn)
163+
return xerrors.WithStackTrace(xerrors.Retryable(errNotReadyConn,
164+
xerrors.Invalid(c),
165+
xerrors.Invalid(c.session),
166+
))
159167
}
160168

161169
if !c.session.IsAlive() {
162-
return xerrors.WithStackTrace(errNotReadyConn)
170+
return xerrors.WithStackTrace(xerrors.Retryable(errNotReadyConn,
171+
xerrors.Invalid(c),
172+
xerrors.Invalid(c.session),
173+
))
163174
}
164175

165176
err := c.session.Exec(ctx, "select 1")
@@ -178,7 +189,10 @@ func (c *Conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (common.
178189

179190
func (c *Conn) Close() (finalErr error) {
180191
if !c.closed.CompareAndSwap(false, true) {
181-
return xerrors.WithStackTrace(errConnClosedEarly)
192+
return xerrors.WithStackTrace(xerrors.Retryable(errConnClosedEarly,
193+
xerrors.Invalid(c),
194+
xerrors.Invalid(c.session),
195+
))
182196
}
183197

184198
defer func() {

internal/xsql/xquery/errors.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ package xquery
33
import (
44
"database/sql/driver"
55
"errors"
6-
7-
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
86
)
97

108
var (
119
ErrUnsupported = driver.ErrSkip
1210
errDeprecated = driver.ErrSkip
13-
errConnClosedEarly = xerrors.Retryable(errors.New("conn closed early"), xerrors.InvalidObject())
14-
errNotReadyConn = xerrors.Retryable(errors.New("conn not ready"), xerrors.InvalidObject())
11+
errConnClosedEarly = errors.New("conn closed early")
12+
errNotReadyConn = errors.New("conn not ready")
1513
)

0 commit comments

Comments
 (0)