|
|
@@ -128,9 +128,19 @@ func (c *cowHostList) remove(ip net.IP) bool {
|
|
|
// exposes the correct functions for the retry policy logic to evaluate correctly.
|
|
|
type RetryableQuery interface {
|
|
|
Attempts() int
|
|
|
+ SetConsistency(c Consistency)
|
|
|
GetConsistency() Consistency
|
|
|
}
|
|
|
|
|
|
+type RetryType uint16
|
|
|
+
|
|
|
+const (
|
|
|
+ Retry RetryType = 0x00 // retry on same connection
|
|
|
+ RetryNextHost RetryType = 0x01 // retry on another connection
|
|
|
+ Ignore RetryType = 0x02 // ignore error and return result
|
|
|
+ Rethrow RetryType = 0x03 // raise error and stop retrying
|
|
|
+)
|
|
|
+
|
|
|
// RetryPolicy interface is used by gocql to determine if a query can be attempted
|
|
|
// again after a retryable error has been received. The interface allows gocql
|
|
|
// users to implement their own logic to determine if a query can be attempted
|
|
|
@@ -140,6 +150,7 @@ type RetryableQuery interface {
|
|
|
// interface.
|
|
|
type RetryPolicy interface {
|
|
|
Attempt(RetryableQuery) bool
|
|
|
+ GetRetryType(error) RetryType
|
|
|
}
|
|
|
|
|
|
// SimpleRetryPolicy has simple logic for attempting a query a fixed number of times.
|
|
|
@@ -162,6 +173,10 @@ func (s *SimpleRetryPolicy) Attempt(q RetryableQuery) bool {
|
|
|
return q.Attempts() <= s.NumRetries
|
|
|
}
|
|
|
|
|
|
+func (s *SimpleRetryPolicy) GetRetryType(err error) RetryType {
|
|
|
+ return RetryNextHost
|
|
|
+}
|
|
|
+
|
|
|
// ExponentialBackoffRetryPolicy sleeps between attempts
|
|
|
type ExponentialBackoffRetryPolicy struct {
|
|
|
NumRetries int
|
|
|
@@ -194,6 +209,70 @@ func getExponentialTime(min time.Duration, max time.Duration, attempts int) time
|
|
|
return time.Duration(napDuration)
|
|
|
}
|
|
|
|
|
|
+func (e *ExponentialBackoffRetryPolicy) GetRetryType(err error) RetryType {
|
|
|
+ return RetryNextHost
|
|
|
+}
|
|
|
+
|
|
|
+// DowngradingConsistencyRetryPolicy: Next retry will be with the next consistency level
|
|
|
+// provided in the slice
|
|
|
+//
|
|
|
+// On a read timeout: the operation is retried with the next provided consistency
|
|
|
+// level.
|
|
|
+//
|
|
|
+// On a write timeout: if the operation is an :attr:`~.UNLOGGED_BATCH`
|
|
|
+// and at least one replica acknowledged the write, the operation is
|
|
|
+// retried with the next consistency level. Furthermore, for other
|
|
|
+// write types, if at least one replica acknowledged the write, the
|
|
|
+// timeout is ignored.
|
|
|
+//
|
|
|
+// On an unavailable exception: if at least one replica is alive, the
|
|
|
+// operation is retried with the next provided consistency level.
|
|
|
+
|
|
|
+type DowngradingConsistencyRetryPolicy struct {
|
|
|
+ ConsistencyLevelsToTry []Consistency
|
|
|
+}
|
|
|
+
|
|
|
+func (d *DowngradingConsistencyRetryPolicy) Attempt(q RetryableQuery) bool {
|
|
|
+ currentAttempt := q.Attempts()
|
|
|
+
|
|
|
+ if currentAttempt > len(d.ConsistencyLevelsToTry) {
|
|
|
+ return false
|
|
|
+ } else if currentAttempt > 0 {
|
|
|
+ q.SetConsistency(d.ConsistencyLevelsToTry[currentAttempt-1])
|
|
|
+ if gocqlDebug {
|
|
|
+ Logger.Printf("%T: set consistency to %q\n",
|
|
|
+ d,
|
|
|
+ d.ConsistencyLevelsToTry[currentAttempt-1])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+func (d *DowngradingConsistencyRetryPolicy) GetRetryType(err error) RetryType {
|
|
|
+ switch t := err.(type) {
|
|
|
+ case *RequestErrUnavailable:
|
|
|
+ if t.Alive > 0 {
|
|
|
+ return Retry
|
|
|
+ }
|
|
|
+ return Rethrow
|
|
|
+ case *RequestErrWriteTimeout:
|
|
|
+ if t.WriteType == "SIMPLE" || t.WriteType == "BATCH" || t.WriteType == "COUNTER" {
|
|
|
+ if t.Received > 0 {
|
|
|
+ return Ignore
|
|
|
+ }
|
|
|
+ return Rethrow
|
|
|
+ }
|
|
|
+ if t.WriteType == "UNLOGGED_BATCH" {
|
|
|
+ return Retry
|
|
|
+ }
|
|
|
+ return Rethrow
|
|
|
+ case *RequestErrReadTimeout:
|
|
|
+ return Retry
|
|
|
+ default:
|
|
|
+ return RetryNextHost
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func (e *ExponentialBackoffRetryPolicy) napTime(attempts int) time.Duration {
|
|
|
return getExponentialTime(e.Min, e.Max, attempts)
|
|
|
}
|