Skip to content

Commit 5cf474f

Browse files
rcohenmacodycushing
authored andcommitted
adding retry logic for retriable errors
1 parent 41b956e commit 5cf474f

File tree

11 files changed

+352
-29
lines changed

11 files changed

+352
-29
lines changed

crud/helpers.go

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"log"
88
"reflect"
9+
"regexp"
910
"strconv"
1011
"strings"
1112
"time"
@@ -17,6 +18,7 @@ import (
1718
)
1819

1920
var (
21+
MaxRetries uint = 6
2022
FiveMinutes time.Duration = 5 * time.Minute
2123
TwoHours time.Duration = 120 * time.Minute
2224
DefaultTimeout = &schema.ResourceTimeout{
@@ -136,14 +138,29 @@ func LoadBalancerResourceGet(s BaseCrud, workReq *baremetal.WorkRequest) (id str
136138
return id, false, nil
137139
}
138140

141+
func exponentialBackoffSleep(retryNum uint) {
142+
secondsToSleep := 1 << retryNum
143+
log.Printf("[DEBUG] Got a retriable error. Waiting %d seconds and trying again...", secondsToSleep)
144+
time.Sleep(time.Duration(secondsToSleep) * time.Second)
145+
}
146+
147+
func isRetriableError(error string) bool {
148+
//all errors are retriable except 400, 401, 412, and 409 with code InvalidatedRetryToken
149+
lowerCaseError := strings.ToLower(error)
150+
statusMatch, _ := regexp.MatchString("status\\s*:\\s*4(0[01]|12)", lowerCaseError)
151+
codeMatch, _ := regexp.MatchString("code\\s*:\\s*invalidatedretrytoken", lowerCaseError)
152+
return !statusMatch && !codeMatch
153+
}
154+
139155
func CreateResource(d *schema.ResourceData, sync ResourceCreator) (e error) {
156+
return createResourceWithRetry(d, sync, 1)
157+
}
158+
159+
func createResourceWithRetry(d *schema.ResourceData, sync ResourceCreator, retryNum uint) (e error) {
140160
if e = sync.Create(); e != nil {
141-
// Check for conflicts and retry
142-
// This happens with concurrent volume attachments, etc
143-
if strings.Contains(strings.ToLower(e.Error()), "try again later") {
144-
log.Println("[DEBUG] Resource creation conflicts with other resources. Waiting 10 seconds and trying again...")
145-
time.Sleep(10 * time.Second)
146-
e = CreateResource(d, sync)
161+
if isRetriableError(e.Error()) && retryNum <= MaxRetries {
162+
exponentialBackoffSleep(retryNum)
163+
e = createResourceWithRetry(d, sync, retryNum+1)
147164
}
148165
return e
149166
}
@@ -166,8 +183,18 @@ func CreateResource(d *schema.ResourceData, sync ResourceCreator) (e error) {
166183
}
167184

168185
func ReadResource(sync ResourceReader) (e error) {
186+
return readResourceWithRetry(sync, 1)
187+
}
188+
189+
func readResourceWithRetry(sync ResourceReader, retryNum uint) (e error) {
169190
if e = sync.Get(); e != nil {
170191
handleMissingResourceError(sync, &e)
192+
if e != nil {
193+
if isRetriableError(e.Error()) && retryNum <= MaxRetries {
194+
exponentialBackoffSleep(retryNum)
195+
e = readResourceWithRetry(sync, retryNum+1)
196+
}
197+
}
171198
return
172199
}
173200

@@ -188,8 +215,16 @@ func ReadResource(sync ResourceReader) (e error) {
188215
}
189216

190217
func UpdateResource(d *schema.ResourceData, sync ResourceUpdater) (e error) {
218+
return updateResourceWithRetry(d, sync, 1)
219+
}
220+
221+
func updateResourceWithRetry(d *schema.ResourceData, sync ResourceUpdater, retryNum uint) (e error) {
191222
d.Partial(true)
192223
if e = sync.Update(); e != nil {
224+
if isRetriableError(e.Error()) && retryNum <= MaxRetries {
225+
exponentialBackoffSleep(retryNum)
226+
e = updateResourceWithRetry(d, sync, retryNum+1)
227+
}
193228
return
194229
}
195230
d.Partial(false)
@@ -203,9 +238,17 @@ func UpdateResource(d *schema.ResourceData, sync ResourceUpdater) (e error) {
203238
// () -> Pending -> Deleted.
204239
// Finally, sets the ResourceData state to empty.
205240
func DeleteResource(d *schema.ResourceData, sync ResourceDeleter) (e error) {
241+
return deleteResourceWithRetry(d, sync, 1)
242+
}
243+
244+
func deleteResourceWithRetry(d *schema.ResourceData, sync ResourceDeleter, retryNum uint) (e error) {
206245
if e = sync.Delete(); e != nil {
207246
handleMissingResourceError(sync, &e)
208247
if e != nil {
248+
if isRetriableError(e.Error()) && retryNum <= MaxRetries {
249+
exponentialBackoffSleep(retryNum)
250+
e = deleteResourceWithRetry(d, sync, retryNum+1)
251+
}
209252
return
210253
}
211254
}

vendor/github.com/MustWin/baremetal-sdk-go/Makefile

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/MustWin/baremetal-sdk-go/constants.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/MustWin/baremetal-sdk-go/database_db_system.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/MustWin/baremetal-sdk-go/identity.go

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/MustWin/baremetal-sdk-go/object_storage_bucket.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/MustWin/baremetal-sdk-go/request.go

Lines changed: 8 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)