github.com/team-ide/go-dialect@v1.9.20/vitess/vterrors/aggregate.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package vterrors 18 19 import ( 20 "sort" 21 "strings" 22 23 vtrpcpb "github.com/team-ide/go-dialect/vitess/vtrpc" 24 ) 25 26 // A list of all vtrpcpb.Code, ordered by priority. These priorities are 27 // used when aggregating multiple errors in VtGate. 28 // Higher priority error codes are more urgent for users to see. They are 29 // prioritized based on the following question: assuming a scatter query produced multiple 30 // errors, which of the errors is the most likely to give the user useful information 31 // about why the query failed and how they should proceed? 32 const ( 33 // Informational errors. 34 PriorityOK = iota 35 PriorityCanceled 36 PriorityAlreadyExists 37 PriorityOutOfRange 38 // Potentially retryable errors. 39 PriorityUnavailable 40 PriorityDeadlineExceeded 41 PriorityAborted 42 PriorityFailedPrecondition 43 PriorityClusterEvent 44 // Permanent errors. 45 PriorityResourceExhausted 46 PriorityUnknown 47 PriorityUnauthenticated 48 PriorityPermissionDenied 49 PriorityInvalidArgument 50 PriorityNotFound 51 PriorityUnimplemented 52 // Serious errors. 53 PriorityInternal 54 PriorityDataLoss 55 ) 56 57 var errorPriorities = map[vtrpcpb.Code]int{ 58 vtrpcpb.Code_OK: PriorityOK, 59 vtrpcpb.Code_CANCELED: PriorityCanceled, 60 vtrpcpb.Code_UNKNOWN: PriorityUnknown, 61 vtrpcpb.Code_INVALID_ARGUMENT: PriorityInvalidArgument, 62 vtrpcpb.Code_DEADLINE_EXCEEDED: PriorityDeadlineExceeded, 63 vtrpcpb.Code_NOT_FOUND: PriorityNotFound, 64 vtrpcpb.Code_ALREADY_EXISTS: PriorityAlreadyExists, 65 vtrpcpb.Code_PERMISSION_DENIED: PriorityPermissionDenied, 66 vtrpcpb.Code_UNAUTHENTICATED: PriorityUnauthenticated, 67 vtrpcpb.Code_RESOURCE_EXHAUSTED: PriorityResourceExhausted, 68 vtrpcpb.Code_FAILED_PRECONDITION: PriorityFailedPrecondition, 69 vtrpcpb.Code_ABORTED: PriorityAborted, 70 vtrpcpb.Code_OUT_OF_RANGE: PriorityOutOfRange, 71 vtrpcpb.Code_UNIMPLEMENTED: PriorityUnimplemented, 72 vtrpcpb.Code_INTERNAL: PriorityInternal, 73 vtrpcpb.Code_UNAVAILABLE: PriorityUnavailable, 74 vtrpcpb.Code_DATA_LOSS: PriorityDataLoss, 75 vtrpcpb.Code_CLUSTER_EVENT: PriorityClusterEvent, 76 } 77 78 // Aggregate aggregates several errors into a single one. 79 // The resulting error code will be the one with the highest 80 // priority as defined by the priority constants in this package. 81 func Aggregate(errors []error) error { 82 if len(errors) == 0 { 83 return nil 84 } 85 if len(errors) == 1 { 86 return errors[0] 87 } 88 return New(aggregateCodes(errors), aggregateErrors(errors)) 89 } 90 91 func aggregateCodes(errors []error) vtrpcpb.Code { 92 highCode := vtrpcpb.Code_OK 93 for _, e := range errors { 94 code := Code(e) 95 if errorPriorities[code] > errorPriorities[highCode] { 96 highCode = code 97 } 98 } 99 return highCode 100 } 101 102 // ConcatenateErrors aggregates an array of errors into a single error by string concatenation. 103 func aggregateErrors(errs []error) string { 104 errStrs := make([]string, 0, len(errs)) 105 for _, e := range errs { 106 errStrs = append(errStrs, e.Error()) 107 } 108 // sort the error strings so we always have deterministic ordering 109 sort.Strings(errStrs) 110 return strings.Join(errStrs, "\n") 111 }