|
7 | 7 | "errors"
|
8 | 8 | "fmt"
|
9 | 9 | "net/http"
|
| 10 | + "strings" |
10 | 11 | "sync"
|
11 | 12 | "time"
|
12 | 13 |
|
@@ -225,19 +226,26 @@ func (ds *SQLDatasource) handleQuery(ctx context.Context, req backend.DataQuery,
|
225 | 226 | // If there's a query error that didn't exceed the
|
226 | 227 | // context deadline retry the query
|
227 | 228 | 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())) |
241 | 249 | }
|
242 | 250 | }
|
243 | 251 | }
|
@@ -302,6 +310,15 @@ func (ds *SQLDatasource) checkWithRetries(conn dbConnection) (*backend.CheckHeal
|
302 | 310 | if err == nil {
|
303 | 311 | return result, err
|
304 | 312 | }
|
| 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)) |
305 | 322 | }
|
306 | 323 |
|
307 | 324 | // TODO: failed health checks don't return an error
|
@@ -332,3 +349,12 @@ func (ds *SQLDatasource) ping(conn dbConnection) error {
|
332 | 349 |
|
333 | 350 | return conn.db.PingContext(ctx)
|
334 | 351 | }
|
| 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 | +} |
0 commit comments