@@ -33,13 +33,20 @@ import (
33
33
"regexp"
34
34
"strconv"
35
35
"strings"
36
+ "time"
36
37
"unicode/utf8"
37
38
38
39
logging "github.com/op/go-logging"
39
40
)
40
41
41
42
var logger = logging .MustGetLogger ("couchdb" )
42
43
44
+ //maximum number of retry attempts
45
+ const maxRetries = 3
46
+
47
+ //time between retry attempts in milliseconds
48
+ const retryWaitTime = 100
49
+
43
50
// DBOperationResponse is body for successful database calls.
44
51
type DBOperationResponse struct {
45
52
Ok bool
@@ -994,14 +1001,57 @@ func (couchInstance *CouchInstance) handleRequest(method, connectURL string, dat
994
1001
transport .DisableCompression = false
995
1002
client .Transport = transport
996
1003
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
+
1001
1049
}
1002
1050
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
+ }
1005
1055
1006
1056
//set the return code for the couchDB request
1007
1057
couchDBReturn .StatusCode = resp .StatusCode
@@ -1010,18 +1060,22 @@ func (couchInstance *CouchInstance) handleRequest(method, connectURL string, dat
1010
1060
//in this case, the http request succeeded but CouchDB is reporing an error
1011
1061
if resp .StatusCode >= 400 {
1012
1062
1063
+ //Read the response body
1013
1064
jsonError , err := ioutil .ReadAll (resp .Body )
1014
1065
if err != nil {
1015
1066
return nil , nil , err
1016
1067
}
1017
1068
1018
- logger .Debugf ("Couch DB error status code=%v error=%s" , resp .StatusCode , jsonError )
1019
-
1020
1069
errorBytes := []byte (jsonError )
1021
1070
1071
+ //marshal the response
1022
1072
json .Unmarshal (errorBytes , & couchDBReturn )
1023
1073
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 )
1025
1079
1026
1080
}
1027
1081
0 commit comments