github.com/vedadiyan/sqlparser@v1.0.0/pkg/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/vedadiyan/sqlparser/pkg/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  }