github.com/cloudwego/kitex@v0.9.0/pkg/remote/trans_errors.go (about) 1 /* 2 * Copyright 2021 CloudWeGo 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 remote 18 19 import ( 20 "errors" 21 "fmt" 22 23 "github.com/cloudwego/kitex/pkg/kerrors" 24 ) 25 26 // corresponding with thrift TApplicationException, cannot change it 27 const ( 28 UnknownApplicationException = 0 29 UnknownMethod = 1 30 InvalidMessageTypeException = 2 31 WrongMethodName = 3 32 BadSequenceID = 4 33 MissingResult = 5 34 InternalError = 6 35 ProtocolError = 7 36 InvalidTransform = 8 37 InvalidProtocol = 9 38 UnsupportedClientType = 10 39 // kitex's own type id from number 20 40 UnknownService = 20 41 NoServiceName = 21 42 ) 43 44 var defaultTransErrorMessage = map[int32]string{ 45 UnknownApplicationException: "unknown application exception", 46 UnknownMethod: "unknown method", 47 InvalidMessageTypeException: "invalid message type", 48 WrongMethodName: "wrong method name", 49 BadSequenceID: "bad sequence ID", 50 MissingResult: "missing result", 51 InternalError: "unknown internal error", 52 ProtocolError: "unknown protocol error", 53 InvalidTransform: "Invalid transform", 54 InvalidProtocol: "Invalid protocol", 55 UnsupportedClientType: "Unsupported client type", 56 UnknownService: "unknown service", 57 } 58 59 // TransError is the error that can be transmitted, it corresponds to TApplicationException in Thrift 60 type TransError struct { 61 message string 62 typeID int32 63 rawErr error 64 } 65 66 // Error implements the error interface. 67 func (e TransError) Error() string { 68 if e.message != "" { 69 return e.message 70 } 71 return defaultTransErrorMessage[e.typeID] 72 } 73 74 // TypeID return err type id 75 func (e TransError) TypeID() int32 { 76 return e.typeID 77 } 78 79 // Unwrap the transError to expose raw error 80 func (e TransError) Unwrap() error { 81 return e.rawErr 82 } 83 84 // Is to check if inner error that transError wrap is target error 85 func (e TransError) Is(target error) bool { 86 return e == target || errors.Is(e.rawErr, target) 87 } 88 89 // AppendMessage append extra msg for TransError 90 func (e TransError) AppendMessage(extraMsg string) *TransError { 91 if extraMsg == "" { 92 return &e 93 } 94 msg := fmt.Sprintf("%s %s", e.message, extraMsg) 95 // should not modify origin error 96 return &TransError{message: msg, typeID: e.typeID, rawErr: e.rawErr} 97 } 98 99 // NewTransErrorWithMsg to build TransError with typeID and errMsg 100 func NewTransErrorWithMsg(typeID int32, message string) *TransError { 101 return &TransError{message: message, typeID: typeID} 102 } 103 104 // NewTransError to build TransError with typeID and rawErr. 105 // rawErr can be used by errors.Is(target) to check err type, like read timeout. 106 func NewTransError(typeID int32, err error) *TransError { 107 if e, ok := err.(*TransError); ok { 108 return e 109 } 110 // biz error should add biz info which is convenient to be recognized by client side 111 var dErr *kerrors.DetailedError 112 if errors.As(err, &dErr) && dErr.Is(kerrors.ErrBiz) { 113 if e, ok := dErr.Unwrap().(*TransError); ok { 114 e = e.AppendMessage(fmt.Sprintf("[%s]", kerrors.ErrBiz.Error())) 115 return e 116 } 117 } 118 if typeID == InternalError { 119 // try to get more specific err type if typeID is InternalError 120 if tID, ok := err.(TypeId); ok { 121 typeID = tID.TypeId() 122 } else if tID, ok := err.(TypeID); ok { 123 typeID = tID.TypeID() 124 } 125 } 126 return &TransError{message: err.Error(), typeID: typeID, rawErr: err} 127 } 128 129 // TypeId is used to assert Error with has 'TypeID() int32' 130 type TypeID interface { 131 TypeID() int32 132 } 133 134 // TypeId is used to assert Error with has 'TypeId() int32' like TApplicationException 135 type TypeId interface { 136 TypeId() int32 137 }