forked from dolthub/vitess
/
aggregate.go
94 lines (86 loc) · 3.04 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
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package vterrors
import (
"sort"
"strings"
vtrpcpb "github.com/youtube/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")
}