Skip to content

Commit cbe044b

Browse files
authored
Merge pull request #10 from codeGROOVE-dev/fork
Apply Google Style Guide & performance optimizations
2 parents b995c04 + ed41a4b commit cbe044b

File tree

3 files changed

+53
-47
lines changed

3 files changed

+53
-47
lines changed

README.md

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
[![Release](https://img.shields.io/github/release/codeGROOVE-dev/retry-go.svg?style=flat-square)](https://github.com/codeGROOVE-dev/retry-go/releases/latest)
44
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
5-
![GitHub Actions](https://github.com/codeGROOVE-dev/retry-go/actions/workflows/workflow.yaml/badge.svg)
65
[![Go Report Card](https://goreportcard.com/badge/github.com/codeGROOVE-dev/retry-go?style=flat-square)](https://goreportcard.com/report/github.com/codeGROOVE-dev/retry-go)
76
[![Go Reference](https://pkg.go.dev/badge/github.com/codeGROOVE-dev/retry-go.svg)](https://pkg.go.dev/github.com/codeGROOVE-dev/retry-go)
87

@@ -26,6 +25,8 @@ This fork retains the original v4 API provided by the retry-go codebase, and is
2625

2726
# SYNOPSIS
2827

28+
For full package documentation, see https://pkg.go.dev/github.com/codeGROOVE-dev/retry-go
29+
2930
HTTP GET with retry:
3031

3132
url := "http://example.com"
@@ -80,6 +81,8 @@ HTTP GET with retry with data:
8081

8182
[More examples](https://github.com/codeGROOVE-dev/retry-go/tree/master/examples)
8283

84+
85+
8386
# SEE ALSO
8487

8588
* [giantswarm/retry-go](https://github.com/giantswarm/retry-go) - slightly
@@ -102,16 +105,8 @@ nonintuitive interface (for me)
102105

103106
Contributions are very much welcome.
104107

105-
### Makefile
106-
107-
Makefile provides several handy rules, like README.md `generator` , `setup` for prepare build/dev environment, `test`, `cover`, etc...
108-
109-
Try `make help` for more information.
110-
111108
### Before pull request
112109

113-
> maybe you need `make setup` in order to setup environment
114-
115110
please try:
116111
* run tests (`make test`)
117112
* run linter (`make lint`)

options.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,19 @@ type OnRetryFunc func(attempt uint, err error)
2020
// The attempt parameter is the zero-based index of the attempt.
2121
type DelayTypeFunc func(attempt uint, err error, config *Config) time.Duration
2222

23-
// Timer represents the timer used to track time for a retry.
23+
// Timer provides an interface for time operations in retry logic.
24+
// This abstraction allows for mocking time in tests and implementing
25+
// custom timing behaviors. The standard implementation uses time.After.
2426
type Timer interface {
27+
// After returns a channel that sends the current time after the duration elapses.
28+
// It should behave like time.After.
2529
After(time.Duration) <-chan time.Time
2630
}
2731

28-
// Config contains all retry configuration.
32+
// Config holds all configuration options for retry behavior.
33+
// It is typically populated using Option functions and should not be
34+
// constructed directly. Use the various Option functions like Attempts,
35+
// Delay, and RetryIf to configure retry behavior.
2936
type Config struct {
3037
attempts uint
3138
attemptsForError map[error]uint
@@ -36,9 +43,9 @@ type Config struct {
3643
retryIf RetryIfFunc
3744
delayType DelayTypeFunc
3845
lastErrorOnly bool
39-
context context.Context
40-
timer Timer
41-
wrapContextErrorWithLastError bool
46+
context context.Context
47+
timer Timer
48+
wrapLastErr bool // wrap context error with last function error
4249

4350
maxBackOffN uint
4451
}
@@ -58,10 +65,10 @@ func (c *Config) validate() error {
5865

5966
// Ensure we have required functions
6067
if c.retryIf == nil {
61-
return fmt.Errorf("retryIf function cannot be nil")
68+
return fmt.Errorf("retry if function cannot be nil")
6269
}
6370
if c.delayType == nil {
64-
return fmt.Errorf("delayType function cannot be nil")
71+
return fmt.Errorf("delay type function cannot be nil")
6572
}
6673
if c.timer == nil {
6774
return fmt.Errorf("timer cannot be nil")
@@ -73,7 +80,9 @@ func (c *Config) validate() error {
7380
return nil
7481
}
7582

76-
// Option represents an option for retry.
83+
// Option configures retry behavior. Options are applied in the order provided
84+
// to Do or DoWithData. Later options override earlier ones if they modify the
85+
// same configuration field.
7786
type Option func(*Config)
7887

7988
func emptyOption(c *Config) {}
@@ -380,8 +389,8 @@ func WithTimer(t Timer) Option {
380389
// retry.Attempts(0),
381390
// retry.WrapContextErrorWithLastError(true),
382391
// )
383-
func WrapContextErrorWithLastError(wrapContextErrorWithLastError bool) Option {
392+
func WrapContextErrorWithLastError(wrap bool) Option {
384393
return func(c *Config) {
385-
c.wrapContextErrorWithLastError = wrapContextErrorWithLastError
394+
c.wrapLastErr = wrap
386395
}
387396
}

retry.go

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,21 @@ func DoWithData[T any](retryableFunc RetryableFuncWithData[T], opts ...Option) (
180180
}
181181
attempt++
182182

183-
// Wait for next attempt
184-
delayDuration := delay(config, attempt, err)
183+
// Wait for next attempt - inline delay calculation for performance
184+
delayTime := config.delayType(attempt, err, config)
185+
if delayTime < 0 {
186+
delayTime = 0
187+
}
188+
if config.maxDelay > 0 && delayTime > config.maxDelay {
189+
delayTime = config.maxDelay
190+
}
191+
185192
select {
186-
case <-config.timer.After(delayDuration):
193+
case <-config.timer.After(delayTime):
187194
case <-config.context.Done():
188195
contextErr := context.Cause(config.context)
189196
if config.lastErrorOnly {
190-
if config.wrapContextErrorWithLastError && err != nil {
197+
if config.wrapLastErr && err != nil {
191198
return emptyT, fmt.Errorf("%w: %w", contextErr, err)
192199
}
193200
return emptyT, contextErr
@@ -228,14 +235,25 @@ type Error []error
228235
// Error returns a string representation of all errors that occurred during retry attempts.
229236
// Each error is prefixed with its attempt number.
230237
func (e Error) Error() string {
231-
logWithNumber := make([]string, len(e))
238+
if len(e) == 0 {
239+
return "All attempts fail:"
240+
}
241+
242+
// Use strings.Builder for efficient string concatenation
243+
var b strings.Builder
244+
b.WriteString("All attempts fail:")
245+
232246
for i, err := range e {
233247
if err != nil {
234-
logWithNumber[i] = fmt.Sprintf("#%d: %s", i+1, err.Error())
248+
b.WriteByte('\n')
249+
b.WriteByte('#')
250+
b.WriteString(fmt.Sprint(i + 1))
251+
b.WriteString(": ")
252+
b.WriteString(err.Error())
235253
}
236254
}
237-
238-
return fmt.Sprintf("All attempts fail:\n%s", strings.Join(logWithNumber, "\n"))
255+
256+
return b.String()
239257
}
240258

241259
// Is reports whether any error in e matches target.
@@ -315,30 +333,14 @@ func IsRecoverable(err error) bool {
315333
// Is implements error matching for unrecoverableError.
316334
// It supports errors.Is by checking if the target is also an unrecoverableError.
317335
func (unrecoverableError) Is(err error) bool {
318-
_, isUnrecoverable := err.(unrecoverableError)
319-
return isUnrecoverable
336+
_, ok := err.(unrecoverableError)
337+
return ok
320338
}
321339

322340
func unpackUnrecoverable(err error) error {
323-
if unrecoverable, isUnrecoverable := err.(unrecoverableError); isUnrecoverable {
324-
return unrecoverable.error
341+
if u, ok := err.(unrecoverableError); ok {
342+
return u.error
325343
}
326-
327344
return err
328345
}
329346

330-
func delay(config *Config, attempt uint, err error) time.Duration {
331-
delayTime := config.delayType(attempt, err, config)
332-
333-
// Ensure delay is non-negative
334-
if delayTime < 0 {
335-
delayTime = 0
336-
}
337-
338-
// Apply max delay cap if configured
339-
if config.maxDelay > 0 && delayTime > config.maxDelay {
340-
delayTime = config.maxDelay
341-
}
342-
343-
return delayTime
344-
}

0 commit comments

Comments
 (0)