Skip to content

Commit 6e84229

Browse files
author
Chris Elder
committed
FAB-2437 Add retry logic for failed CouchDB actions
Motivation for this change: Network connection failures and CouchDB error 500 status code should be retried at least once before returning error to high level components. Change-Id: Ied4430ddde226c92876108819a9b545e28f83e05 Signed-off-by: Chris Elder <[email protected]>
1 parent 1e2e9cb commit 6e84229

File tree

1 file changed

+63
-9
lines changed

1 file changed

+63
-9
lines changed

core/ledger/util/couchdb/couchdb.go

+63-9
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,20 @@ import (
3333
"regexp"
3434
"strconv"
3535
"strings"
36+
"time"
3637
"unicode/utf8"
3738

3839
logging "github.com/op/go-logging"
3940
)
4041

4142
var logger = logging.MustGetLogger("couchdb")
4243

44+
//maximum number of retry attempts
45+
const maxRetries = 3
46+
47+
//time between retry attempts in milliseconds
48+
const retryWaitTime = 100
49+
4350
// DBOperationResponse is body for successful database calls.
4451
type DBOperationResponse struct {
4552
Ok bool
@@ -994,14 +1001,57 @@ func (couchInstance *CouchInstance) handleRequest(method, connectURL string, dat
9941001
transport.DisableCompression = false
9951002
client.Transport = transport
9961003

997-
//Execute http request
998-
resp, err := client.Do(req)
999-
if err != nil {
1000-
return nil, nil, err
1004+
//create the return objects for couchDB
1005+
var resp *http.Response
1006+
var errResp error
1007+
couchDBReturn := &DBReturn{}
1008+
1009+
//attempt the http request for the max number of retries
1010+
for attempts := 0; attempts < maxRetries; attempts++ {
1011+
1012+
//Execute http request
1013+
resp, errResp = client.Do(req)
1014+
1015+
//if an error is not detected then drop out of the retry
1016+
if errResp == nil && resp != nil && resp.StatusCode < 500 {
1017+
break
1018+
}
1019+
1020+
//if this is an error, record the retry error, else this is a 500 error
1021+
if errResp != nil {
1022+
1023+
//Log the error with the retry count and continue
1024+
logger.Debugf("Retrying couchdb request. Retry:%v Error:%v",
1025+
attempts+1, errResp.Error())
1026+
1027+
} else {
1028+
1029+
//Read the response body
1030+
jsonError, err := ioutil.ReadAll(resp.Body)
1031+
if err != nil {
1032+
return nil, nil, err
1033+
}
1034+
1035+
errorBytes := []byte(jsonError)
1036+
1037+
//Unmarshal the response
1038+
json.Unmarshal(errorBytes, &couchDBReturn)
1039+
1040+
//Log the 500 error with the retry count and continue
1041+
logger.Debugf("Retrying couchdb request. Retry:%v Couch DB Error:%s, Status Code:%v Reason:%v",
1042+
attempts+1, couchDBReturn.Error, resp.Status, couchDBReturn.Reason)
1043+
1044+
}
1045+
1046+
//sleep for specified sleep time, then retry
1047+
time.Sleep(retryWaitTime * time.Millisecond)
1048+
10011049
}
10021050

1003-
//create the return object for couchDB
1004-
couchDBReturn := &DBReturn{}
1051+
//if the error present, return the error
1052+
if errResp != nil {
1053+
return nil, nil, errResp
1054+
}
10051055

10061056
//set the return code for the couchDB request
10071057
couchDBReturn.StatusCode = resp.StatusCode
@@ -1010,18 +1060,22 @@ func (couchInstance *CouchInstance) handleRequest(method, connectURL string, dat
10101060
//in this case, the http request succeeded but CouchDB is reporing an error
10111061
if resp.StatusCode >= 400 {
10121062

1063+
//Read the response body
10131064
jsonError, err := ioutil.ReadAll(resp.Body)
10141065
if err != nil {
10151066
return nil, nil, err
10161067
}
10171068

1018-
logger.Debugf("Couch DB error status code=%v error=%s", resp.StatusCode, jsonError)
1019-
10201069
errorBytes := []byte(jsonError)
10211070

1071+
//marshal the response
10221072
json.Unmarshal(errorBytes, &couchDBReturn)
10231073

1024-
return nil, couchDBReturn, fmt.Errorf("Couch DB Error: %s", couchDBReturn.Reason)
1074+
logger.Debugf("Couch DB Error:%s, Status Code:%v, Reason:%s",
1075+
couchDBReturn.Error, resp.StatusCode, couchDBReturn.Reason)
1076+
1077+
return nil, couchDBReturn, fmt.Errorf("Couch DB Error:%s, Status Code:%v, Reason:%s",
1078+
couchDBReturn.Error, resp.StatusCode, couchDBReturn.Reason)
10251079

10261080
}
10271081

0 commit comments

Comments
 (0)