-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy patherrors.go
151 lines (121 loc) · 4.18 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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Package qberrors provides common errors to standardize error handling across
// Quickbae golang projects.
//
// See https://blog.golang.org/go1.13-errors
package qberrors
import (
"fmt"
"net/http"
)
const (
defaultMsg = "internal error"
defaultCode = http.StatusInternalServerError
)
// ErrSafe errors.
var (
BadRequest = ErrSafe{"bad request", http.StatusBadRequest}
InvalidDataType = ErrSafe{"data type not valid", http.StatusBadRequest}
InvalidInput = ErrSafe{"input not valid", http.StatusBadRequest}
InvalidSyntax = ErrSafe{"syntax not valid", http.StatusBadRequest}
NotFound = ErrSafe{"not found", http.StatusNotFound}
ServceUnavailable = ErrSafe{"service unavailable", http.StatusServiceUnavailable}
)
// ErrSafe is an error that is assumed to be safe to show to the user. Errors
// that wrap ErrSafe are also assumed to be safe to show the user, inclusive of
// all subsequent wraps up the chain.
type ErrSafe struct {
Message string
StatusCode int
}
func (e ErrSafe) Error() string { return e.Message }
// SafeErrorf returns a wrapped ErrSafe given the format specifier.
func SafeErrorf(err error, format string, a ...interface{}) error {
format += ": %w"
a = append(a, err)
return fmt.Errorf(format, a...)
}
// Error is implemented by errors.
type Error interface {
// Upstream returns the error chain that caused showing the user an error.
// It is assumed that the error chain is unsafe to show the user.
Upstream() error
// Retry returns whether the operation should be retried.
Retry() bool
}
// ErrClient is an error due to client input.
// The operation should not be retried.
type ErrClient struct {
upstream error
safe error
}
// Client returns an ErrClient.
func Client(err error) *ErrClient { return &ErrClient{err, BadRequest} }
func (e ErrClient) Unwrap() error { return e.safe }
func (e ErrClient) Error() string { return e.safe.Error() }
// Upstream implements Error.Upstream.
func (e ErrClient) Upstream() error { return e.upstream }
// Retry implements Error.Retry.
func (e ErrClient) Retry() bool { return false }
// Safe sets ErrClient.safe as err.
// TODO add variadic argument that wraps err
func (e *ErrClient) Safe(err error) error {
e.safe = err
return e
}
// Safef sets ErrClient.safe as a wrapped err.
func (e *ErrClient) Safef(err error, format string, a ...interface{}) error {
e.safe = SafeErrorf(err, format, a...)
return e
}
// ErrInternal is an error with the application.
// The operation should not be retried.
type ErrInternal struct {
upstream error
safe error
}
// Internal returns an ErrInternal.
func Internal(err error) *ErrInternal {
return &ErrInternal{err, ErrSafe{defaultMsg, defaultCode}}
}
func (e ErrInternal) Unwrap() error { return e.safe }
func (e ErrInternal) Error() string { return e.safe.Error() }
// Upstream implements Error.Upstream.
func (e ErrInternal) Upstream() error { return e.upstream }
// Retry implements Error.Retry.
func (e ErrInternal) Retry() bool { return false }
// Safe sets ErrInternal.safe as err.
// TODO add variadic argument that wraps err
func (e *ErrInternal) Safe(err error) error {
e.safe = err
return e
}
// Safef sets ErrInternal.safe as a wrapped err.
func (e *ErrInternal) Safef(err error, format string, a ...interface{}) error {
e.safe = SafeErrorf(err, format, a...)
return e
}
// ErrService is an error connecting to a dependent service.
// The operation can be retried.
type ErrService struct {
upstream error
safe error
}
// Service returns an ErrService.
func Service(err error) *ErrService { return &ErrService{err, ServceUnavailable} }
func (e ErrService) Unwrap() error { return e.safe }
func (e ErrService) Error() string { return e.safe.Error() }
// Upstream implements Error.Upstream.
func (e ErrService) Upstream() error { return e.upstream }
// Retry implements Error.Retry.
func (e ErrService) Retry() bool { return true }
// Safe sets ErrService.safe as err.
// TODO add variadic argument that wraps err
func (e *ErrService) Safe(err error) error {
e.safe = err
return e
}
// Safef sets ErrService.safe as a wrapped err.
func (e *ErrService) Safef(err error, format string, a ...interface{}) error {
e.safe = SafeErrorf(err, format, a...)
return e
}