This repository has been archived by the owner on Dec 14, 2021. It is now read-only.
/
errors.go
256 lines (219 loc) · 6.79 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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.
package errors
import (
"fmt"
"io"
"strings"
errs "github.com/pkg/errors"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
)
type ErrType string
// These constants represent error types
const (
AlreadyExists ErrType = "already exists"
Internal ErrType = "internal"
InvalidArgument ErrType = "invalid argument"
NotFound ErrType = "not found"
OutOfRange ErrType = "out of range"
PermissionDenied ErrType = "permission denied"
Unavailable ErrType = "unavailable"
Unknown ErrType = "unknown"
)
// GetErrType returns the type of err
func GetErrType(err error) ErrType {
switch errs.Cause(err).(type) {
case *ErrAlreadyExists:
return AlreadyExists
case *ErrInternal:
return Internal
case *ErrInvalidArgument:
return InvalidArgument
case *ErrNotFound:
return NotFound
case *ErrPermissionDenied:
return PermissionDenied
case *ErrUnavailable:
return Unavailable
}
return Unknown
}
// IsPermissionDenied returns whether error type is PermissionDenied
func IsPermissionDenied(err error) bool {
return GetErrType(err) == PermissionDenied
}
// IsNotFound returns whether error type is NotFound
func IsNotFound(err error) bool {
return GetErrType(err) == NotFound
}
// IsInvalidArgument returns whether error type is InvalidArgument
func IsInvalidArgument(err error) bool {
return GetErrType(err) == InvalidArgument
}
// IsInternal returns whether error type is Internal
func IsInternal(err error) bool {
return GetErrType(err) == Internal
}
// IsAlreadyExists returns whether error type is AlreadyExists
func IsAlreadyExists(err error) bool {
return GetErrType(err) == AlreadyExists
}
// IsUnavailable returns whether error type is Unavailable
func IsUnavailable(err error) bool {
return GetErrType(err) == Unavailable
}
// BuildGRPCError returns the error with a GRPC code
func BuildGRPCError(err error) error {
if err == nil {
return nil
}
code := grpc.Code(err)
if code != codes.Unknown {
return err // it already is a gRPC error
}
switch errs.Cause(err).(type) {
case *ErrAlreadyExists:
code = codes.AlreadyExists
case *ErrInternal:
code = codes.Internal
case *ErrInvalidArgument:
code = codes.InvalidArgument
case *ErrNotFound:
code = codes.NotFound
case *ErrPermissionDenied:
code = codes.PermissionDenied
case *ErrUnavailable:
code = codes.Unavailable
}
switch err {
case context.Canceled:
code = codes.Canceled
case io.EOF:
code = codes.OutOfRange
}
return grpc.Errorf(code, err.Error())
}
// FromGRPCError creates a regular error with the same type as the gRPC error
func FromGRPCError(err error) error {
if err == nil {
return nil
}
if GetErrType(err) != Unknown {
return err
}
code := grpc.Code(err)
desc := grpc.ErrorDesc(err)
switch code {
case codes.AlreadyExists:
return NewErrAlreadyExists(strings.TrimSuffix(desc, " already exists"))
case codes.Internal:
return NewErrInternal(strings.TrimPrefix(desc, "Internal error: "))
case codes.InvalidArgument:
if split := strings.Split(desc, " not valid: "); len(split) == 2 {
return NewErrInvalidArgument(split[0], split[1])
}
return NewErrInvalidArgument("Argument", desc)
case codes.NotFound:
return NewErrNotFound(strings.TrimSuffix(desc, " not found"))
case codes.PermissionDenied:
return NewErrPermissionDenied(strings.TrimPrefix(desc, "permission denied: "))
case codes.Unavailable:
return NewErrUnavailable(strings.TrimPrefix(desc, "unavailable: "))
case codes.Unknown: // This also includes all non-gRPC errors
if desc == "EOF" {
return io.EOF
}
return errs.New(desc)
}
return NewErrInternal(fmt.Sprintf("[%s] %s", code, desc))
}
// NewErrAlreadyExists returns a new ErrAlreadyExists for the given entitiy
func NewErrAlreadyExists(entity string) error {
return &ErrAlreadyExists{entity: entity}
}
// ErrAlreadyExists indicates that an entity already exists
type ErrAlreadyExists struct {
entity string
}
// Error implements the error interface
func (err ErrAlreadyExists) Error() string {
return fmt.Sprintf("%s already exists", err.entity)
}
// NewErrInternal returns a new ErrInternal with the given message
func NewErrInternal(message string) error {
return &ErrInternal{message: message}
}
// ErrInternal indicates that an internal error occured
type ErrInternal struct {
message string
}
// Error implements the error interface
func (err ErrInternal) Error() string {
return fmt.Sprintf("Internal error: %s", err.message)
}
// NewErrInvalidArgument returns a new ErrInvalidArgument for the given entitiy
func NewErrInvalidArgument(argument string, reason string) error {
return &ErrInvalidArgument{argument: argument, reason: reason}
}
// ErrInvalidArgument indicates that an argument was invalid
type ErrInvalidArgument struct {
argument string
reason string
}
// Error implements the error interface
func (err ErrInvalidArgument) Error() string {
return fmt.Sprintf("%s not valid: %s", err.argument, err.reason)
}
// NewErrNotFound returns a new ErrNotFound for the given entitiy
func NewErrNotFound(entity string) error {
return &ErrNotFound{entity: entity}
}
// ErrNotFound indicates that an entity was not found
type ErrNotFound struct {
entity string
}
// Error implements the error interface
func (err ErrNotFound) Error() string {
return fmt.Sprintf("%s not found", err.entity)
}
// NewErrPermissionDenied returns a new ErrPermissionDenied with the given reason
func NewErrPermissionDenied(reason string) error {
return &ErrPermissionDenied{reason: reason}
}
// ErrPermissionDenied indicates that permissions were not sufficient
type ErrPermissionDenied struct {
reason string
}
// Error implements the error interface
func (err ErrPermissionDenied) Error() string {
return fmt.Sprintf("permission denied: %s", err.reason)
}
// NewErrUnavailable returns a new ErrUnavailable with the given reason
func NewErrUnavailable(reason string) error {
return &ErrUnavailable{reason: reason}
}
// ErrUnavailable indicates that permissions were not sufficient
type ErrUnavailable struct {
reason string
}
// Error implements the error interface
func (err ErrUnavailable) Error() string {
return fmt.Sprintf("unavailable: %s", err.reason)
}
// Wrapf returns an error annotating err with the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
return errs.Wrapf(err, format, args...)
}
// Wrap returns an error annotating err with message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
return errs.Wrap(err, message)
}
// New returns an error with the supplied message.
// New also records the stack trace at the point it was called.
func New(message string) error {
return errs.New(message)
}