forked from dugancathal/dynago
-
Notifications
You must be signed in to change notification settings - Fork 0
/
errors.go
97 lines (84 loc) · 3.02 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
package dynago
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"github.com/bemobi/dynago/internal/codes"
"github.com/bemobi/dynago/internal/dynamodb"
)
// Error encapsulates errors coming from amazon/dynamodb.
// It is returned whenever we get a non-2xx result from dynamodb.
type Error struct {
Type codes.ErrorCode // Parsed and mapped down type
AmazonRawType string // Raw error type from amazon
Exception string // Exception from amazon
Message string // Raw message from amazon
Request *http.Request // If available, HTTP request
RequestBody []byte // If available, raw request body bytes
Response *http.Response // If available, HTTP response
ResponseBody []byte // If available, raw response body bytes
}
// Error formats this error as a string.
func (e *Error) Error() string {
exception := e.Exception
if exception == "" {
exception = e.AmazonRawType
}
return fmt.Sprintf("dynago.Error(%s): %s: %s", e.Type, exception, e.Message)
}
// Parse and create the error
func (e *Error) parse(input *inputError) {
e.AmazonRawType = input.AmazonRawType
e.Message = input.Message
parts := strings.Split(e.AmazonRawType, "#")
if len(parts) >= 2 {
e.Exception = parts[1]
if conf, ok := amazonErrorMap[e.Exception]; ok {
e.Type = conf.MappedError
}
}
}
func buildError(req *http.Request, body []byte, response *http.Response, respBody []byte) error {
e := &Error{
Request: req,
RequestBody: body,
Response: response,
ResponseBody: respBody,
}
dest := &inputError{}
if err := json.Unmarshal(respBody, dest); err == nil {
e.parse(dest)
} else {
e.Message = err.Error()
}
return e
}
type inputError struct {
AmazonRawType string `json:"__type"`
Message string `json:"message"`
}
// All the mapped error codes
const (
ErrorUnknown codes.ErrorCode = iota
ErrorConditionFailed // Conditional put/update failed; condition not met
ErrorCollectionSizeExceeded // Item collection (local secondary index) too large
ErrorThroughputExceeded // Exceeded provisioned throughput for table or shard
ErrorNotFound // Resource referenced by key not found
ErrorInternalFailure // Internal server error
ErrorAuth // Encapsulates various authorization errors
ErrorInvalidParameter // Encapsulates many forms of invalid input errors
ErrorServiceUnavailable // Amazon service unavailable
ErrorThrottling // Amazon is throttling us, try later
ErrorResourceInUse // Tried to create existing table, delete a table in CREATING state, etc.
// DynamoDB Streams-specific errors
ErrorExpiredIterator // Iterator is no longer valid
ErrorTrimmedData // Attempted to access data older than 24h
)
var amazonErrorMap map[string]*dynamodb.ErrorConfig
func init() {
amazonErrorMap = make(map[string]*dynamodb.ErrorConfig, len(dynamodb.MappedErrors))
for i, conf := range dynamodb.MappedErrors {
amazonErrorMap[conf.AmazonCode] = &dynamodb.MappedErrors[i]
}
}