/
errors.go
375 lines (315 loc) · 13.2 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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
//
// Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved.
//
// Licensed under the Universal Permissive License v 1.0 as shown at
// https://oss.oracle.com/licenses/upl/
//
//go:generate stringer -type=ErrorCode -output errorcode_string.go
// Package nosqlerr defines types and error code constants that represent errors
// which may return by the NoSQL client.
package nosqlerr
import (
"fmt"
)
// Error represents an error that wraps the error code, error message and an
// optional cause of the error.
//
// This implements the error interface.
type Error struct {
// Code specifies the error code.
Code ErrorCode `json:"code"`
// Message specifies the description of error.
Message string `json:"message"`
// Cause optionally specifies the cause of error.
Cause error `json:"cause,omitempty"`
}
// New creates an error with the specified error code and message.
func New(code ErrorCode, msgFmt string, msgArgs ...interface{}) *Error {
return &Error{
Code: code,
Message: fmt.Sprintf(msgFmt, msgArgs...),
}
}
// NewWithCause creates an error with the specified error code, message and the cause of error.
func NewWithCause(code ErrorCode, cause error, msgFmt string, msgArgs ...interface{}) *Error {
return &Error{
Code: code,
Message: fmt.Sprintf(msgFmt, msgArgs...),
Cause: cause,
}
}
// Error returns a descriptive message for the error.
func (e *Error) Error() string {
if e.Cause == nil {
return fmt.Sprintf("[%s]: %s", e.Code.String(), e.Message)
}
return fmt.Sprintf("[%s]: %s. Caused by:\n\t%s", e.Code.String(), e.Message, e.Cause.Error())
}
// Retryable returns whether the error is retryable.
func (e *Error) Retryable() bool {
return retryableErrors[e.Code]
}
// retryableErrors represents a map whose keys are the error codes of pre-defined
// errors that are retryable. This is used as a fast lookup table to check if
// an error is retryable.
var retryableErrors map[ErrorCode]bool = map[ErrorCode]bool{
SecurityInfoUnavailable: true,
RetryAuthentication: true,
ServerError: true,
TableBusy: true,
OperationLimitExceeded: true,
ReadLimitExceeded: true,
WriteLimitExceeded: true,
SizeLimitExceeded: true,
}
// NewIllegalArgument creates an IllegalArgument error with the specified message.
func NewIllegalArgument(msgFmt string, msgArgs ...interface{}) *Error {
return New(IllegalArgument, msgFmt, msgArgs...)
}
// NewIllegalState creates an IllegalState error with the specified message.
func NewIllegalState(msgFmt string, msgArgs ...interface{}) *Error {
return New(IllegalState, msgFmt, msgArgs...)
}
// NewRequestTimeout creates a RequestTimeout error with the specified message.
func NewRequestTimeout(msgFmt string, msgArgs ...interface{}) *Error {
return New(RequestTimeout, msgFmt, msgArgs...)
}
// Is checks if the specified error is an Error value and the error code
// matches any of the expected error codes if specified.
func Is(err error, expectedCodes ...ErrorCode) bool {
e, ok := err.(*Error)
if !ok {
return false
}
if len(expectedCodes) == 0 {
return true
}
for _, code := range expectedCodes {
if e.Code == code {
return true
}
}
return false
}
// IsTableNotFound returns true if the specified error is a TableNotFound error,
// otherwise returns false.
func IsTableNotFound(err error) bool {
return Is(err, TableNotFound)
}
// IsIllegalArgument returns true if the specified error is an IllegalArgument error,
// otherwise returns false.
func IsIllegalArgument(err error) bool {
return Is(err, IllegalArgument)
}
// IsSecurityInfoUnavailable returns true if the specified error is a SecurityInfoUnavailable error,
// otherwise returns false.
func IsSecurityInfoUnavailable(err error) bool {
return Is(err, SecurityInfoUnavailable)
}
// ErrorCode represents the error code.
// Error codes are divided into categories as follows:
//
// 1. Error codes for user-generated errors, range from 1 to 50(exclusive).
// These include illegal arguments, exceeding size limits for some objects,
// resource not found, etc.
//
// 2. Error codes for user throttling, range from 50 to 100(exclusive).
//
// 3. Error codes for server issues, range from 100 to 150(exclusive).
//
// 3.1 Retryable server issues, range from 100 to 125(exclusive), that represent
// internal problems, presumably temporary, and need to be sent back to the
// application for retry.
//
// 3.2 Other server issues, begin from 125.
// These include server illegal state, unknown server error, etc.
// They might be retryable, or not.
//
type ErrorCode int
const (
// NoError represents there is no error.
NoError ErrorCode = iota // 0
// UnknownOperation error represents the operation attempted is unknown.
UnknownOperation // 1
// TableNotFound error represents the operation attempted to access a table
// that does not exist or is not in a visible state.
TableNotFound // 2
// IndexNotFound error represents the operation attempted to access an index
// that does not exist or is not in a visible state.
IndexNotFound // 3
// IllegalArgument error represents the application provided an illegal
// argument for the operation.
IllegalArgument // 4
// RowSizeLimitExceeded error represents an attempt has been made to create
// a row with a size that exceeds the system defined limit.
//
// This is used for cloud service only.
RowSizeLimitExceeded // 5
// KeySizeLimitExceeded error represents an attempt has been made to create
// a row with a primary key or index key size that exceeds the system defined limit.
//
// This is used for cloud service only.
KeySizeLimitExceeded // 6
// BatchOpNumberLimitExceeded error represents that the number of operations
// included in Client.WriteMultiple operation exceeds the system defined limit.
//
// This is used for cloud service only.
BatchOpNumberLimitExceeded // 7
// RequestSizeLimitExceeded error represents that the size of a request
// exceeds the system defined limit.
//
// This is used for cloud service only.
RequestSizeLimitExceeded // 8
// TableExists error represents the operation attempted to create a table
// but the named table already exists.
TableExists // 9
// IndexExists error represents the operation attempted to create an index
// for a table but the named index already exists.
IndexExists // 10
// InvalidAuthorization error represents the client provides an invalid
// authorization string in the request header.
InvalidAuthorization // 11
// InsufficientPermission error represents an application does not have
// sufficient permission to perform a request.
InsufficientPermission // 12
// ResourceExists error represents the operation attempted to create a
// resource but it already exists.
ResourceExists // 13
// ResourceNotFound error represents the operation attempted to access a
// resource that does not exist or is not in a visible state.
ResourceNotFound // 14
// TableLimitExceeded error represents an attempt has been made to create a
// number of tables that exceeds the system defined limit.
//
// This is used for cloud service only.
TableLimitExceeded // 15
// IndexLimitExceeded error represents an attempt has been made to create
// more indexes on a table than the system defined limit.
//
// This is used for cloud service only.
IndexLimitExceeded // 16
// BadProtocolMessage error represents there is an error in the protocol
// used by client and server to exchange informations.
// This error is not visible to applications. It is wrapped as an IllegalArgument
// error and returned to applications.
BadProtocolMessage // 17
// EvolutionLimitExceeded error represents an attempt has been made to evolve
// the schema of a table more times than allowed by the system defined limit.
//
// This is used for cloud service only.
EvolutionLimitExceeded // 18
// TableDeploymentLimitExceeded error represents an attempt has been made to
// create or modify a table using limits that exceed the maximum allowed for
// a single table.
//
// This is system-defined limit, used for cloud service only.
TableDeploymentLimitExceeded // 19
// TenantDeploymentLimitExceeded error represents an attempt has been made to
// create or modify a table using limits that cause the tenant's aggregate
// resources to exceed the maximum allowed for a tenant.
//
// This is system-defined limit, used for cloud service only.
TenantDeploymentLimitExceeded // 20
// OperationNotSupported error represents the operation attempted is not supported.
// This may be related to on-premise vs cloud service configurations.
OperationNotSupported // 21
// EtagMismatch is used only by the cloud REST service.
EtagMismatch // 22
// CannotCancelWorkRequest is used only by the cloud REST service.
CannotCancelWorkRequest // 23
// UnsupportedProtocol error indicates the server does not support the
// given driver protocol version. The driver should decrement its internal
// protocol version (and accompanying logic) and try again.
UnsupportedProtocol // 24
)
const (
// ReadLimitExceeded error represents that the provisioned read throughput
// has been exceeded.
//
// Operations resulting in this error can be retried but it is recommended
// that callers use a delay before retrying in order to minimize the chance
// that a retry will also be throttled. Applications should attempt to avoid
// throttling errors by rate limiting themselves to the degree possible.
//
// Retries and behavior related to throttling can be managed by configuring
// the DefaultRetryHandler for client or by providing a custom implementation
// of the RetryHandler interface for client.
//
// This is used for cloud service only.
ReadLimitExceeded ErrorCode = iota + 50 // 50
// WriteLimitExceeded error represents that the provisioned write throughput
// has been exceeded.
//
// Operations resulting in this error can be retried but it is recommended
// that callers use a delay before retrying in order to minimize the chance
// that a retry will also be throttled. Applications should attempt to avoid
// throttling errors by rate limiting themselves to the degree possible.
//
// Retries and behavior related to throttling can be managed by configuring
// the DefaultRetryHandler for client or by providing a custom implementation
// of the RetryHandler interface for client.
//
// This is used for cloud service only.
WriteLimitExceeded // 51
// SizeLimitExceeded error represents a table size limit has been exceeded
// by writing more data than the table can support.
// This error is not retryable because the conditions that lead to it being
// retuned, while potentially transient, typically require user intervention.
SizeLimitExceeded // 52
// OperationLimitExceeded error represents the operation attempted has exceeded
// the allowed limits for non-data operations defined by the system.
//
// This error is returned when a non-data operation is throttled.
// This can happen if an application attempts too many control operations
// such as table creation, deletion, or similar methods. Such operations
// do not use throughput or capacity provisioned for a given table but they
// consume system resources and their use is limited.
//
// Operations resulting in this error can be retried but it is recommended
// that callers use a relatively large delay before retrying in order to
// minimize the chance that a retry will also be throttled.
//
// This is used for cloud service only.
OperationLimitExceeded // 53
)
const (
// RequestTimeout error represents the request cannot be processed or does
// not complete when the specified timeout duration elapses.
//
// If a retry handler is configured for the client it is possible that the
// request has been retried a number of times before the timeout occurs.
RequestTimeout ErrorCode = iota + 100 // 100
// ServerError represents there is an internal system problem.
// Most system problems are temporary.
// The operation that leads to this error may need to retry.
ServerError // 101
// ServiceUnavailable error represents the requested service is currently unavailable.
// This is usually a temporary error.
// The operation that leads to this error may need to retry.
ServiceUnavailable // 102
// TableBusy error represents the table is in use or busy.
// This error may be returned when a table operation fails.
// Note that only one modification operation at a time is allowed on a table.
TableBusy // 103
// SecurityInfoUnavailable error represents the security information is not
// ready in the system.
// This error will occur as the system acquires security information and
// must be retried in order for authorization to work properly.
//
// This is used for cloud service only.
SecurityInfoUnavailable // 104
// RetryAuthentication error represents the authentication failed and may need to retry.
// This may be returned by kvstore.AccessTokenProvider in the following cases:
//
// 1. Authentication information was not provided in the request header.
// 2. The user session has expired. By default kvstore.AccessTokenProvider
// will automatically retry authentication with user credentials provided.
//
RetryAuthentication // 105
)
const (
// UnknownError represents an unknown error has occurred on the server.
UnknownError ErrorCode = iota + 125 // 125
// IllegalState error represents an illegal state.
IllegalState // 126
)