-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy patherrors.go
76 lines (64 loc) · 2.12 KB
/
errors.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
package statemachine
import (
"errors"
"time"
"github.com/lytics/metafora"
)
// ExceededErrorRate is returned by error handlers in an Error Message when
// retry logic has been exhausted for a handler and it should transition to
// Failed.
var ExceededErrorRate = errors.New("exceeded error rate")
// Err represents an error that occurred while a stateful handler was running.
//
// NewErr was added to allow callers to construct an instance from an underlying error.
// The underlying error is now preserved so that Err can be converted back using errors.As
// This is useful for custom error handlers that wish to inspect underlying error types
// and decision accordingly.
type Err struct {
Time time.Time `json:"timestamp"`
Err string `json:"error"`
baseErr error
}
// NewErr constructs an Err from an underlying error e.
func NewErr(e error, t time.Time) Err {
return Err{Err: e.Error(), Time: t, baseErr: e}
}
// Error implements the Error interface.
func (e Err) Error() string {
return e.Err
}
// Unwrap returns baseErr.
func (e Err) Unwrap() error {
return e.baseErr
}
// ErrHandler functions should return Run, Sleep, or Fail messages depending on
// the rate of errors.
//
// Either ErrHandler and/or StateStore should trim the error slice to keep it
// from growing without bound.
type ErrHandler func(task metafora.Task, errs []Err) (*Message, []Err)
const (
DefaultErrLifetime = -4 * time.Hour
DefaultErrMax = 8
)
// DefaultErrHandler returns a Fail message if 8 errors have occurred in 4
// hours. Otherwise it enters the Sleep state for 10 minutes before trying
// again.
func DefaultErrHandler(_ metafora.Task, errs []Err) (*Message, []Err) {
recent := time.Now().Add(DefaultErrLifetime)
strikes := 0
for _, err := range errs {
if err.Time.After(recent) {
strikes++
}
}
if len(errs) > DefaultErrMax {
errs = errs[len(errs)-DefaultErrMax:]
}
if strikes >= DefaultErrMax {
// Return a new error to transition to Failed as well as the original
// errors to store what caused this failure.
return ErrorMessage(ExceededErrorRate), errs
}
return SleepMessage(time.Now().Add(10 * time.Minute)), errs
}