Skip to content

Commit 8e0ba07

Browse files
authored
Merge pull request #1766 from 0chain/feature/authorizer-retry
Feature: add retries for authorizers queries
2 parents 0dece85 + 130c0d7 commit 8e0ba07

File tree

1 file changed

+68
-14
lines changed

1 file changed

+68
-14
lines changed

zcnbridge/authorizers_query.go

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package zcnbridge
33
import (
44
"encoding/json"
55
"fmt"
6-
coreClient "github.com/0chain/gosdk/core/client"
76
"io"
87
"math"
98
"net/http"
109
"strings"
1110
"sync"
11+
"time"
12+
13+
coreClient "github.com/0chain/gosdk/core/client"
1214

1315
"github.com/0chain/gosdk/core/common"
1416
"github.com/0chain/gosdk/zcnbridge/errors"
@@ -41,6 +43,14 @@ type (
4143
eventsChannelType chan []JobResult
4244
)
4345

46+
const (
47+
// Represents max amount of retries, when timeout status was received
48+
maxCallbackRetries = 5
49+
50+
// Represents callback retry delay for http calls, when timeout status was received
51+
callbackRetryDelay = time.Second * 5
52+
)
53+
4454
var (
4555
client *http.Client
4656
)
@@ -282,7 +292,7 @@ func queryAuthorizer(au *AuthorizerNode, request *requestHandler, responseChanne
282292
}
283293
req.URL.RawQuery = q.Encode()
284294
Logger.Info(req.URL.String())
285-
resp, body := readResponse(client.Do(req))
295+
resp, body := readResponse(func() (*http.Response, error) { return client.Do(req) })
286296
resp.AuthorizerID = au.ID
287297

288298
if resp.error != nil {
@@ -313,22 +323,66 @@ func queryAuthorizer(au *AuthorizerNode, request *requestHandler, responseChanne
313323
responseChannel <- resp
314324
}
315325

316-
func readResponse(response *http.Response, err error) (res *authorizerResponse, body []byte) {
326+
func readResponse(responseCallback func() (*http.Response, error)) (res *authorizerResponse, body []byte) {
317327
res = &authorizerResponse{}
318-
if err != nil {
319-
err = errors.Wrap("authorizer_post_process", "failed to call the authorizer", err)
320-
Logger.Error("request response error", zap.Error(err))
321-
}
322328

323-
if response == nil {
324-
res.error = err
325-
Logger.Error("response is empty", zap.Error(err))
326-
return res, nil
329+
var (
330+
retryTicker *time.Ticker
331+
retryCounter int
332+
333+
response *http.Response
334+
err error
335+
)
336+
337+
for {
338+
if retryTicker != nil {
339+
select {
340+
case <-retryTicker.C:
341+
default:
342+
}
343+
}
344+
345+
response, err = responseCallback()
346+
if response == nil {
347+
res.error = err
348+
Logger.Error("response is empty", zap.Error(err))
349+
return res, nil
350+
}
351+
352+
if err != nil {
353+
err = errors.Wrap("authorizer_post_process", "failed to call the authorizer", err)
354+
Logger.Error("request response error", zap.Error(err))
355+
}
356+
357+
if response.StatusCode == 408 {
358+
if retryTicker == nil {
359+
retryTicker = time.NewTicker(callbackRetryDelay)
360+
}
361+
362+
if retryCounter >= maxCallbackRetries {
363+
err = errors.Wrap("authorizer_post_process", fmt.Sprintf("error %d", response.StatusCode), err)
364+
Logger.Error("request response status", zap.Error(err))
365+
366+
break
367+
}
368+
369+
retryCounter++
370+
371+
continue
372+
}
373+
374+
if response.StatusCode >= 400 {
375+
err = errors.Wrap("authorizer_post_process", fmt.Sprintf("error %d", response.StatusCode), err)
376+
Logger.Error("request response status", zap.Error(err))
377+
378+
break
379+
}
380+
381+
break
327382
}
328383

329-
if response.StatusCode >= 400 {
330-
err = errors.Wrap("authorizer_post_process", fmt.Sprintf("error %d", response.StatusCode), err)
331-
Logger.Error("request response status", zap.Error(err))
384+
if retryTicker != nil {
385+
retryTicker.Stop()
332386
}
333387

334388
body, er := io.ReadAll(response.Body)

0 commit comments

Comments
 (0)