Skip to content

Commit 56f98e9

Browse files
committed
Merge remote-tracking branch 'upstream/master' into do-with-data
2 parents 9452dc2 + 7855000 commit 56f98e9

File tree

2 files changed

+55
-52
lines changed

2 files changed

+55
-52
lines changed

retry.go

Lines changed: 29 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -162,72 +162,59 @@ func DoWithData[T any](retryableFunc RetryableFuncWithData[T], opts ...Option) (
162162
}
163163
}
164164

165-
var errorLog Error
166-
if !config.lastErrorOnly {
167-
errorLog = make(Error, config.attempts)
168-
} else {
169-
errorLog = make(Error, 1)
170-
}
165+
errorLog := Error{}
171166

172167
attemptsForError := make(map[error]uint, len(config.attemptsForError))
173168
for err, attempts := range config.attemptsForError {
174169
attemptsForError[err] = attempts
175170
}
176171

177-
lastErrIndex := n
178172
shouldRetry := true
179173
for shouldRetry {
180174
t, err := retryableFunc()
175+
if err == nil {
176+
return t, nil
177+
}
181178

182-
if err != nil {
183-
errorLog[lastErrIndex] = unpackUnrecoverable(err)
179+
errorLog = append(errorLog, unpackUnrecoverable(err))
184180

185-
if !config.retryIf(err) {
186-
break
187-
}
181+
if !config.retryIf(err) {
182+
break
183+
}
188184

189-
config.onRetry(n, err)
185+
config.onRetry(n, err)
190186

191-
for errToCheck, attempts := range attemptsForError {
192-
if errors.Is(err, errToCheck) {
193-
attempts--
194-
attemptsForError[errToCheck] = attempts
195-
shouldRetry = shouldRetry && attempts > 0
196-
}
187+
for errToCheck, attempts := range attemptsForError {
188+
if errors.Is(err, errToCheck) {
189+
attempts--
190+
attemptsForError[errToCheck] = attempts
191+
shouldRetry = shouldRetry && attempts > 0
197192
}
193+
}
198194

199-
// if this is last attempt - don't wait
200-
if n == config.attempts-1 {
201-
break
202-
}
195+
// if this is last attempt - don't wait
196+
if n == config.attempts-1 {
197+
break
198+
}
203199

204-
select {
205-
case <-config.timer.After(delay(config, n, err)):
206-
case <-config.context.Done():
207-
if config.lastErrorOnly {
208-
return emptyT, config.context.Err()
209-
}
210-
n++
211-
errorLog[n] = config.context.Err()
212-
return emptyT, errorLog[:lenWithoutNil(errorLog)]
200+
select {
201+
case <-config.timer.After(delay(config, n, err)):
202+
case <-config.context.Done():
203+
if config.lastErrorOnly {
204+
return emptyT, config.context.Err()
213205
}
214206

215-
} else {
216-
return t, nil
207+
return emptyT, append(errorLog, config.context.Err())
217208
}
218209

219210
n++
220211
shouldRetry = shouldRetry && n < config.attempts
221-
222-
if !config.lastErrorOnly {
223-
lastErrIndex = n
224-
}
225212
}
226213

227214
if config.lastErrorOnly {
228-
return emptyT, errorLog[lastErrIndex]
215+
return emptyT, errorLog.Unwrap()
229216
}
230-
return emptyT, errorLog[:lenWithoutNil(errorLog)]
217+
return emptyT, errorLog
231218
}
232219

233220
func newDefaultRetryConfig() *Config {
@@ -251,7 +238,7 @@ type Error []error
251238
// Error method return string representation of Error
252239
// It is an implementation of error interface
253240
func (e Error) Error() string {
254-
logWithNumber := make([]string, lenWithoutNil(e))
241+
logWithNumber := make([]string, len(e))
255242
for i, l := range e {
256243
if l != nil {
257244
logWithNumber[i] = fmt.Sprintf("#%d: %s", i+1, l.Error())
@@ -295,17 +282,7 @@ When you need to unwrap all errors, you should use `WrappedErrors()` instead.
295282
Added in version 4.2.0.
296283
*/
297284
func (e Error) Unwrap() error {
298-
return e[lenWithoutNil(e)-1]
299-
}
300-
301-
func lenWithoutNil(e Error) (count int) {
302-
for _, v := range e {
303-
if v != nil {
304-
count++
305-
}
306-
}
307-
308-
return
285+
return e[len(e)-1]
309286
}
310287

311288
// WrappedErrors returns the list of errors that this Error is wrapping.

retry_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,32 @@ func TestUnwrap(t *testing.T) {
539539
assert.Equal(t, testError, errors.Unwrap(err))
540540
}
541541

542+
func BenchmarkDo(b *testing.B) {
543+
testError := errors.New("test error")
544+
545+
for i := 0; i < b.N; i++ {
546+
Do(
547+
func() error {
548+
return testError
549+
},
550+
Attempts(10),
551+
Delay(0),
552+
)
553+
}
554+
}
555+
556+
func BenchmarkDoNoErrors(b *testing.B) {
557+
for i := 0; i < b.N; i++ {
558+
Do(
559+
func() error {
560+
return nil
561+
},
562+
Attempts(10),
563+
Delay(0),
564+
)
565+
}
566+
}
567+
542568
func TestIsRecoverable(t *testing.T) {
543569
err := errors.New("err")
544570
assert.True(t, IsRecoverable(err))

0 commit comments

Comments
 (0)