44package oci
55
66import (
7+ "fmt"
78 "log"
89 "math/rand"
910 "strings"
@@ -116,6 +117,11 @@ func getDefaultExpectedRetryDuration(response oci_common.OCIOperationResponse, d
116117 return defaultRetryTime
117118 }
118119
120+ if ok , remainingEc := isRetriableByEc (response ); ok && remainingEc != nil {
121+ log .Printf ("[DEBUG] Retrying Eventual consistency..." )
122+ return * remainingEc
123+ }
124+
119125 if response .Response == nil || response .Response .HTTPResponse () == nil {
120126 return 0
121127 }
@@ -156,12 +162,54 @@ func getDefaultExpectedRetryDuration(response oci_common.OCIOperationResponse, d
156162 return defaultRetryTime
157163}
158164
165+ func isRetriableByEc (r oci_common.OCIOperationResponse ) (bool , * time.Duration ) {
166+ if _ , ok := oci_common .IsServiceError (r .Error ); ok {
167+ now := time .Now ()
168+ if r .EndOfWindowTime == nil || r .EndOfWindowTime .Before (now ) {
169+ // either no eventually consistent effects, or they have disappeared by now
170+ Debugln (fmt .Sprintf ("EC.ShouldRetryOperation, no EC or in the past, returning false: endOfWindowTime = %v, now = %v" , r .EndOfWindowTime , now ))
171+ return false , nil
172+ }
173+ // there were eventually consistent effects present at the time of the first request
174+ // and they could still affect the retries
175+ if oci_common .IsErrorAffectedByEventualConsistency (r .Error ) {
176+ // and it's one of the three affected error codes
177+ Debugln (fmt .Sprintf ("EC.ShouldRetryOperation, affected by EC, EC is present: endOfWindowTime = %v, now = %v" , r .EndOfWindowTime , now ))
178+ return true , getRemainingEventualConsistencyDuration (r )
179+ }
180+ return false , nil
181+ }
182+ return false , nil
183+ }
184+
185+ // returns the remaining time with eventual consistency, or nil if there is no eventual consistency
186+ func getRemainingEventualConsistencyDuration (r oci_common.OCIOperationResponse ) * time.Duration {
187+ endOfWindow := oci_common .EcContext .GetEndOfWindow ()
188+ if endOfWindow != nil {
189+ // there was an eventually consistent request
190+ if endOfWindow .After (r .InitialAttemptTime ) {
191+ // and the eventually consistent effects may still be present
192+ remaining := endOfWindow .Sub (time .Now ())
193+ if remaining > 0 {
194+ return & remaining
195+ }
196+ }
197+ }
198+
199+ return nil
200+ }
201+
159202func getIdentityExpectedRetryDuration (response oci_common.OCIOperationResponse , disableNotFoundRetries bool , optionals ... interface {}) time.Duration {
160203 defaultRetryTime := getDefaultExpectedRetryDuration (response , disableNotFoundRetries )
161204 if oci_common .IsNetworkError (response .Error ) {
162205 return defaultRetryTime
163206 }
164207
208+ if ok , remainingEc := isRetriableByEc (response ); ok && remainingEc != nil {
209+ log .Printf ("[DEBUG] Retrying Eventual consistency..." )
210+ return * remainingEc
211+ }
212+
165213 if response .Response == nil || response .Response .HTTPResponse () == nil {
166214 return defaultRetryTime
167215 }
@@ -188,6 +236,11 @@ func getDatabaseExpectedRetryDuration(response oci_common.OCIOperationResponse,
188236 return defaultRetryTime
189237 }
190238
239+ if ok , remainingEc := isRetriableByEc (response ); ok && remainingEc != nil {
240+ log .Printf ("[DEBUG] Retrying Eventual consistency..." )
241+ return * remainingEc
242+ }
243+
191244 if response .Response == nil || response .Response .HTTPResponse () == nil {
192245 return defaultRetryTime
193246 }
@@ -209,6 +262,12 @@ func getObjectstorageServiceExpectedRetryDuration(response oci_common.OCIOperati
209262 if oci_common .IsNetworkError (response .Error ) {
210263 return defaultRetryTime
211264 }
265+
266+ if ok , remainingEc := isRetriableByEc (response ); ok && remainingEc != nil {
267+ log .Printf ("[DEBUG] Retrying Eventual consistency..." )
268+ return * remainingEc
269+ }
270+
212271 if response .Response == nil || response .Response .HTTPResponse () == nil {
213272 return defaultRetryTime
214273 }
0 commit comments