forked from vitessio/vitess
-
Notifications
You must be signed in to change notification settings - Fork 1
/
aggregate.go
106 lines (95 loc) · 3.43 KB
/
aggregate.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
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vterrors
import (
"sort"
"strings"
vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
)
// A list of all vtrpcpb.Code, ordered by priority. These priorities are
// used when aggregating multiple errors in VtGate.
// Higher priority error codes are more urgent for users to see. They are
// prioritized based on the following question: assuming a scatter query produced multiple
// errors, which of the errors is the most likely to give the user useful information
// about why the query failed and how they should proceed?
const (
// Informational errors.
PriorityOK = iota
PriorityCanceled
PriorityAlreadyExists
PriorityOutOfRange
// Potentially retryable errors.
PriorityUnavailable
PriorityDeadlineExceeded
PriorityAborted
PriorityFailedPrecondition
// Permanent errors.
PriorityResourceExhausted
PriorityUnknown
PriorityUnauthenticated
PriorityPermissionDenied
PriorityInvalidArgument
PriorityNotFound
PriorityUnimplemented
// Serious errors.
PriorityInternal
PriorityDataLoss
)
var errorPriorities = map[vtrpcpb.Code]int{
vtrpcpb.Code_OK: PriorityOK,
vtrpcpb.Code_CANCELED: PriorityCanceled,
vtrpcpb.Code_UNKNOWN: PriorityUnknown,
vtrpcpb.Code_INVALID_ARGUMENT: PriorityInvalidArgument,
vtrpcpb.Code_DEADLINE_EXCEEDED: PriorityDeadlineExceeded,
vtrpcpb.Code_NOT_FOUND: PriorityNotFound,
vtrpcpb.Code_ALREADY_EXISTS: PriorityAlreadyExists,
vtrpcpb.Code_PERMISSION_DENIED: PriorityPermissionDenied,
vtrpcpb.Code_UNAUTHENTICATED: PriorityUnauthenticated,
vtrpcpb.Code_RESOURCE_EXHAUSTED: PriorityResourceExhausted,
vtrpcpb.Code_FAILED_PRECONDITION: PriorityFailedPrecondition,
vtrpcpb.Code_ABORTED: PriorityAborted,
vtrpcpb.Code_OUT_OF_RANGE: PriorityOutOfRange,
vtrpcpb.Code_UNIMPLEMENTED: PriorityUnimplemented,
vtrpcpb.Code_INTERNAL: PriorityInternal,
vtrpcpb.Code_UNAVAILABLE: PriorityUnavailable,
vtrpcpb.Code_DATA_LOSS: PriorityDataLoss,
}
// Aggregate aggregates several errors into a single one.
// The resulting error code will be the one with the highest
// priority as defined by the priority constants in this package.
func Aggregate(errors []error) error {
if len(errors) == 0 {
return nil
}
return New(aggregateCodes(errors), aggregateErrors(errors))
}
func aggregateCodes(errors []error) vtrpcpb.Code {
highCode := vtrpcpb.Code_OK
for _, e := range errors {
code := Code(e)
if errorPriorities[code] > errorPriorities[highCode] {
highCode = code
}
}
return highCode
}
// ConcatenateErrors aggregates an array of errors into a single error by string concatenation.
func aggregateErrors(errs []error) string {
errStrs := make([]string, 0, len(errs))
for _, e := range errs {
errStrs = append(errStrs, e.Error())
}
// sort the error strings so we always have deterministic ordering
sort.Strings(errStrs)
return strings.Join(errStrs, "\n")
}