Skip to content

Commit e3b8b30

Browse files
authored
Retry on message (#80)
allow setting messages to retry on
1 parent e30c0ed commit e3b8b30

File tree

3 files changed

+42
-15
lines changed

3 files changed

+42
-15
lines changed

datasource.go

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"errors"
88
"fmt"
99
"net/http"
10+
"strings"
1011
"sync"
1112
"time"
1213

@@ -225,19 +226,26 @@ func (ds *SQLDatasource) handleQuery(ctx context.Context, req backend.DataQuery,
225226
// If there's a query error that didn't exceed the
226227
// context deadline retry the query
227228
if errors.Is(err, ErrorQuery) && !errors.Is(err, context.DeadlineExceeded) {
228-
for i := 0; i < ds.driverSettings.Retries; i++ {
229-
backend.Logger.Warn(fmt.Sprintf("query failed. retrying %d times", i))
230-
db, err := ds.dbReconnect(dbConn, q, cacheKey)
231-
if err != nil {
232-
return nil, err
233-
}
234-
235-
if ds.driverSettings.Pause > 0 {
236-
time.Sleep(time.Duration(ds.driverSettings.Pause * int(time.Second)))
237-
}
238-
res, err = QueryDB(ctx, db, ds.c.Converters(), fillMode, q)
239-
if err == nil {
240-
return res, err
229+
// only retry on messages that contain specific errors
230+
if shouldRetry(ds.driverSettings.RetryOn, err.Error()) {
231+
for i := 0; i < ds.driverSettings.Retries; i++ {
232+
backend.Logger.Warn(fmt.Sprintf("query failed: %s. Retrying %d times", err.Error(), i))
233+
db, err := ds.dbReconnect(dbConn, q, cacheKey)
234+
if err != nil {
235+
return nil, err
236+
}
237+
238+
if ds.driverSettings.Pause > 0 {
239+
time.Sleep(time.Duration(ds.driverSettings.Pause * int(time.Second)))
240+
}
241+
res, err = QueryDB(ctx, db, ds.c.Converters(), fillMode, q)
242+
if err == nil {
243+
return res, err
244+
}
245+
if !shouldRetry(ds.driverSettings.RetryOn, err.Error()) {
246+
return res, err
247+
}
248+
backend.Logger.Warn(fmt.Sprintf("Retry failed: %s", err.Error()))
241249
}
242250
}
243251
}
@@ -302,6 +310,15 @@ func (ds *SQLDatasource) checkWithRetries(conn dbConnection) (*backend.CheckHeal
302310
if err == nil {
303311
return result, err
304312
}
313+
314+
if !shouldRetry(ds.driverSettings.RetryOn, err.Error()) {
315+
break
316+
}
317+
318+
if ds.driverSettings.Pause > 0 {
319+
time.Sleep(time.Duration(ds.driverSettings.Pause * int(time.Second)))
320+
}
321+
backend.Logger.Warn(fmt.Sprintf("connect failed: %s. Retrying %d times", err.Error(), i))
305322
}
306323

307324
// TODO: failed health checks don't return an error
@@ -332,3 +349,12 @@ func (ds *SQLDatasource) ping(conn dbConnection) error {
332349

333350
return conn.db.PingContext(ctx)
334351
}
352+
353+
func shouldRetry(retryOn []string, err string) bool {
354+
for _, r := range retryOn {
355+
if strings.Contains(err, r) {
356+
return true
357+
}
358+
}
359+
return false
360+
}

datasource_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func Test_timeout_retries(t *testing.T) {
148148
}
149149
retries := 5
150150
max := time.Duration(testTimeout) * time.Second
151-
driverSettings := DriverSettings{Retries: retries, Timeout: max}
151+
driverSettings := DriverSettings{Retries: retries, Timeout: max, RetryOn: []string{"deadline"}}
152152
ds := &SQLDatasource{c: timeoutDriver, driverSettings: driverSettings}
153153

154154
key := defaultKey(dsUID)
@@ -190,7 +190,7 @@ func Test_error_retries(t *testing.T) {
190190
}
191191
retries := 5
192192
max := time.Duration(10) * time.Second
193-
driverSettings := DriverSettings{Retries: retries, Timeout: max, Pause: 1}
193+
driverSettings := DriverSettings{Retries: retries, Timeout: max, Pause: 1, RetryOn: []string{"foo"}}
194194
ds := &SQLDatasource{c: timeoutDriver, driverSettings: driverSettings}
195195

196196
key := defaultKey(dsUID)

driver.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type DriverSettings struct {
1616
FillMode *data.FillMissing
1717
Retries int
1818
Pause int
19+
RetryOn []string
1920
}
2021

2122
// Driver is a simple interface that defines how to connect to a backend SQL datasource

0 commit comments

Comments
 (0)