Skip to content

Commit 152f5fc

Browse files
authored
Merge pull request #1609 from ydb-platform/retry-panics
processing of panics in retriers
2 parents f3860a6 + 9b813be commit 152f5fc

File tree

2 files changed

+61
-12
lines changed

2 files changed

+61
-12
lines changed

retry/sql.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ func DoTx(ctx context.Context, db *sql.DB, op func(context.Context, *sql.Tx) err
173173
// DoTxWithResult is a retryer of database/sql transactions with fallbacks on errors
174174
//
175175
// Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental
176-
func DoTxWithResult[T any](ctx context.Context, db *sql.DB, //nolint:funlen
176+
func DoTxWithResult[T any](ctx context.Context, db *sql.DB,
177177
op func(context.Context, *sql.Tx) (T, error),
178178
opts ...doTxOption,
179179
) (T, error) {
@@ -211,17 +211,7 @@ func DoTxWithResult[T any](ctx context.Context, db *sql.DB, //nolint:funlen
211211
return zeroValue, unwrapErrBadConn(xerrors.WithStackTrace(err))
212212
}
213213
defer func() {
214-
if finalErr == nil {
215-
return
216-
}
217-
errRollback := tx.Rollback()
218-
if errRollback == nil {
219-
return
220-
}
221-
finalErr = xerrors.NewWithIssues("",
222-
xerrors.WithStackTrace(finalErr),
223-
xerrors.WithStackTrace(fmt.Errorf("rollback failed: %w", errRollback)),
224-
)
214+
_ = tx.Rollback()
225215
}()
226216
v, err := op(xcontext.MarkRetryCall(ctx), tx)
227217
if err != nil {

retry/sql_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"database/sql"
66
"database/sql/driver"
7+
"errors"
78
"strconv"
89
"testing"
910
"time"
@@ -233,3 +234,61 @@ func TestDoTx(t *testing.T) {
233234
})
234235
}
235236
}
237+
238+
func TestCleanUpResourcesOnPanicInRetryOperation(t *testing.T) {
239+
panicErr := errors.New("test")
240+
t.Run("Do", func(t *testing.T) {
241+
m := &mockConnector{
242+
t: t,
243+
}
244+
db := sql.OpenDB(m)
245+
defer func() {
246+
require.NoError(t, db.Close())
247+
}()
248+
require.Panics(t, func() {
249+
require.Equal(t, 0, db.Stats().OpenConnections)
250+
require.Equal(t, 0, db.Stats().Idle)
251+
require.Equal(t, 0, db.Stats().InUse)
252+
defer func() {
253+
require.Equal(t, 1, db.Stats().OpenConnections)
254+
require.Equal(t, 1, db.Stats().Idle)
255+
require.Equal(t, 0, db.Stats().InUse)
256+
}()
257+
_ = Do(context.Background(), db,
258+
func(ctx context.Context, cc *sql.Conn) error {
259+
require.Equal(t, 1, db.Stats().OpenConnections)
260+
require.Equal(t, 0, db.Stats().Idle)
261+
require.Equal(t, 1, db.Stats().InUse)
262+
panic(panicErr)
263+
},
264+
)
265+
})
266+
})
267+
t.Run("DoTx", func(t *testing.T) {
268+
m := &mockConnector{
269+
t: t,
270+
}
271+
db := sql.OpenDB(m)
272+
defer func() {
273+
require.NoError(t, db.Close())
274+
}()
275+
require.Panics(t, func() {
276+
require.Equal(t, 0, db.Stats().OpenConnections)
277+
require.Equal(t, 0, db.Stats().Idle)
278+
require.Equal(t, 0, db.Stats().InUse)
279+
defer func() {
280+
require.Equal(t, 1, db.Stats().OpenConnections)
281+
require.Equal(t, 1, db.Stats().Idle)
282+
require.Equal(t, 0, db.Stats().InUse)
283+
}()
284+
_ = DoTx(context.Background(), db,
285+
func(ctx context.Context, tx *sql.Tx) error {
286+
require.Equal(t, 1, db.Stats().OpenConnections)
287+
require.Equal(t, 0, db.Stats().Idle)
288+
require.Equal(t, 1, db.Stats().InUse)
289+
panic(panicErr)
290+
},
291+
)
292+
})
293+
})
294+
}

0 commit comments

Comments
 (0)