-
Notifications
You must be signed in to change notification settings - Fork 28
/
timeout.go
79 lines (65 loc) · 2.59 KB
/
timeout.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package timeout
import (
"errors"
"time"
"github.com/failsafe-go/failsafe-go"
"github.com/failsafe-go/failsafe-go/policy"
)
// ErrExceeded is returned when an execution exceeds a configured timeout.
var ErrExceeded = errors.New("timeout exceeded")
// Timeout is a Policy that cancels executions if they exceed a time limit. Any policies composed inside the timeout,
// such as retries, will also be canceled. If the execution is configured with a Context, a child context will be created
// for the execution and canceled when the Timeout is exceeded.
//
// This type is concurrency safe.
type Timeout[R any] interface {
failsafe.Policy[R]
}
type TimeoutBuilder[R any] interface {
// OnTimeoutExceeded registers the listener to be called when the timeout is exceeded.
OnTimeoutExceeded(listener func(event failsafe.ExecutionDoneEvent[R])) TimeoutBuilder[R]
// Build returns a new Timeout using the builder's configuration.
Build() Timeout[R]
}
type timeoutConfig[R any] struct {
timeLimit time.Duration
onTimeoutExceeded func(failsafe.ExecutionDoneEvent[R])
}
var _ TimeoutBuilder[any] = &timeoutConfig[any]{}
type timeout[R any] struct {
config *timeoutConfig[R]
}
// With returns a new Timeout for execution result type R and the timeLimit. The Timeout will cancel executions if they
// exceed a time limit. Any policies composed inside the timeout, such as retries, will also be canceled. If the
// execution is configured with a Context, a child context will be created for the execution and canceled when the
// Timeout is exceeded.
func With[R any](timeLimit time.Duration) Timeout[R] {
return Builder[R](timeLimit).Build()
}
// Builder returns a TimeoutBuilder for execution result type R which builds Timeouts for the timeLimit. The Timeout will
// cancel executions if they exceed a time limit. Any policies composed inside the timeout, such as retries, will also be
// canceled. If the execution is configured with a Context, a child context will be created for the execution and canceled when the Timeout
// is exceeded.
func Builder[R any](timeLimit time.Duration) TimeoutBuilder[R] {
return &timeoutConfig[R]{
timeLimit: timeLimit,
}
}
func (c *timeoutConfig[R]) OnTimeoutExceeded(listener func(event failsafe.ExecutionDoneEvent[R])) TimeoutBuilder[R] {
c.onTimeoutExceeded = listener
return c
}
func (c *timeoutConfig[R]) Build() Timeout[R] {
fbCopy := *c
return &timeout[R]{
config: &fbCopy, // TODO copy base fields
}
}
func (t *timeout[R]) ToExecutor(_ R) any {
te := &timeoutExecutor[R]{
BaseExecutor: &policy.BaseExecutor[R]{},
timeout: t,
}
te.Executor = te
return te
}