Skip to content

Commit f5f6739

Browse files
gregoryduquesnoyjfbus
authored andcommitted
add delayed errors (#7)
* Adding DelayedError * minor fix * langage optimization
1 parent 3f26d94 commit f5f6739

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,27 @@
22

33
`go get github.com/objenious/errorutil`
44

5+
## Delayed errors
6+
7+
```go
8+
func foo() error {
9+
err := bar()
10+
timer := time.Hour
11+
if err != nil {
12+
// it should be delayed 1h later
13+
return errorutil.WithDelay(err, timer)
14+
}
15+
return bar() // will not be delayed
16+
}
17+
18+
func main() {
19+
err := foo()
20+
time.AfterFunc(errorutil.Delay(err), func() {
21+
...
22+
})
23+
}
24+
```
25+
526
## Retryable errors
627

728
```go

delayed.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package errorutil
2+
3+
import (
4+
"github.com/pkg/errors"
5+
"time"
6+
)
7+
8+
// Delayer defines an error that
9+
type Delayer interface {
10+
Delay() time.Duration
11+
}
12+
13+
// Delay return the delay duration of a DelayedError (i.e. implements Delayer).
14+
// If the error is nil or does not implement Delayer or the delay is not a positive value, 0 is returned.
15+
func Delay(err error) time.Duration {
16+
type causer interface {
17+
Cause() error
18+
}
19+
20+
for err != nil {
21+
if delay, ok := err.(Delayer); ok {
22+
return delay.Delay()
23+
}
24+
cause, ok := err.(causer)
25+
if !ok {
26+
break
27+
}
28+
err = cause.Cause()
29+
}
30+
return 0
31+
}
32+
33+
// DelayedError set error delay duration. returns nil if the error is nil.
34+
func WithDelay(err error, duration time.Duration) error {
35+
if err == nil {
36+
return nil
37+
}
38+
return &delayedError{error: err, duration: duration}
39+
}
40+
41+
// NewDelayedError returns a delayed error that formats as the given text and duration.
42+
func NewDelayedError(text string, duration time.Duration) error {
43+
return WithDelay(errors.New(text), duration)
44+
}
45+
46+
type delayedError struct {
47+
error
48+
duration time.Duration
49+
}
50+
51+
52+
func (err *delayedError) Delay() time.Duration {
53+
return err.duration
54+
}
55+
56+
func (err *delayedError) Cause() error {
57+
return err.error
58+
}

delayed_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package errorutil
2+
3+
import (
4+
"github.com/pkg/errors"
5+
"testing"
6+
"time"
7+
)
8+
9+
func TestDelay(t *testing.T) {
10+
11+
// err := errorutil.NewRetryableError("Delayed Error Test")
12+
tests := []struct {
13+
err error
14+
want time.Duration
15+
}{
16+
{nil, 0},
17+
{WithDelay(nil, 0), 0},
18+
{WithDelay(nil, 10), 0},
19+
{WithDelay(errors.New("foo"), 0), 0},
20+
{WithDelay(errors.New("foo"), 10), 10},
21+
}
22+
err := WithDelay(errors.New("foobar"), 10)
23+
if err.Error() != "foobar" {
24+
t.Errorf("WithDelay(%q): got: %v, want %v", err, err.Error(), "foobar")
25+
}
26+
for _, tt := range tests {
27+
got := Delay(tt.err)
28+
if got != tt.want {
29+
t.Errorf("WithDelay(%q): got: %v, want %v", tt.err, got, tt.want)
30+
}
31+
}
32+
}
33+
34+
func TestNewDelayedError(t *testing.T) {
35+
err := NewDelayedError("delayed Error", 10)
36+
if err.Error() != "delayed Error" {
37+
t.Errorf("NewDelayedError expected %s, got %s", "delayed Error", err.Error())
38+
}
39+
}

0 commit comments

Comments
 (0)