github.com/milvus-io/milvus-sdk-go/v2@v2.4.1/merr/utils.go (about) 1 // Licensed to the LF AI & Data foundation under one 2 // or more contributor license agreements. See the NOTICE file 3 // distributed with this work for additional information 4 // regarding copyright ownership. The ASF licenses this file 5 // to you under the Apache License, Version 2.0 (the 6 // "License"); you may not use this file except in compliance 7 // with the License. You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package merr 18 19 import ( 20 "context" 21 "strings" 22 23 "github.com/cockroachdb/errors" 24 25 "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" 26 ) 27 28 // Code returns the error code of the given error, 29 // WARN: DO NOT use this for now 30 func Code(err error) int32 { 31 if err == nil { 32 return 0 33 } 34 35 cause := errors.Cause(err) 36 switch cause := cause.(type) { 37 case milvusError: 38 return cause.code() 39 40 default: 41 if errors.Is(cause, context.Canceled) { 42 return CanceledCode 43 } else if errors.Is(cause, context.DeadlineExceeded) { 44 return TimeoutCode 45 } else { 46 return errUnexpected.code() 47 } 48 } 49 } 50 51 func IsRetryableErr(err error) bool { 52 if err, ok := err.(milvusError); ok { 53 return err.retriable 54 } 55 56 return false 57 } 58 59 func IsCanceledOrTimeout(err error) bool { 60 return errors.IsAny(err, context.Canceled, context.DeadlineExceeded) 61 } 62 63 // Status returns a status according to the given err, 64 // returns Success status if err is nil 65 func Status(err error) *commonpb.Status { 66 if err == nil { 67 return &commonpb.Status{} 68 } 69 70 code := Code(err) 71 return &commonpb.Status{ 72 Code: code, 73 Reason: previousLastError(err).Error(), 74 // Deprecated, for compatibility 75 ErrorCode: oldCode(code), 76 Retriable: IsRetryableErr(err), 77 Detail: err.Error(), 78 } 79 } 80 81 func previousLastError(err error) error { 82 lastErr := err 83 for { 84 nextErr := errors.Unwrap(err) 85 if nextErr == nil { 86 break 87 } 88 lastErr = err 89 err = nextErr 90 } 91 return lastErr 92 } 93 94 func CheckRPCCall(resp interface{}, err error) error { 95 if err != nil { 96 return err 97 } 98 if resp == nil { 99 return errUnexpected 100 } 101 switch resp := resp.(type) { 102 case interface{ GetStatus() *commonpb.Status }: 103 return Error(resp.GetStatus()) 104 case *commonpb.Status: 105 return Error(resp) 106 } 107 return nil 108 } 109 110 func Success(reason ...string) *commonpb.Status { 111 status := Status(nil) 112 // NOLINT 113 status.Reason = strings.Join(reason, " ") 114 return status 115 } 116 117 // Deprecated 118 func StatusWithErrorCode(err error, code commonpb.ErrorCode) *commonpb.Status { 119 if err == nil { 120 return &commonpb.Status{} 121 } 122 123 return &commonpb.Status{ 124 Code: Code(err), 125 Reason: err.Error(), 126 ErrorCode: code, 127 } 128 } 129 130 func oldCode(code int32) commonpb.ErrorCode { 131 switch code { 132 case ErrServiceNotReady.code(): 133 return commonpb.ErrorCode_NotReadyServe 134 135 case ErrCollectionNotFound.code(): 136 return commonpb.ErrorCode_CollectionNotExists 137 138 case ErrParameterInvalid.code(): 139 return commonpb.ErrorCode_IllegalArgument 140 141 case ErrNodeNotMatch.code(): 142 return commonpb.ErrorCode_NodeIDNotMatch 143 144 case ErrCollectionNotFound.code(), ErrPartitionNotFound.code(), ErrReplicaNotFound.code(): 145 return commonpb.ErrorCode_MetaFailed 146 147 case ErrReplicaNotAvailable.code(), ErrChannelNotAvailable.code(), ErrNodeNotAvailable.code(): 148 return commonpb.ErrorCode_NoReplicaAvailable 149 150 case ErrServiceMemoryLimitExceeded.code(): 151 return commonpb.ErrorCode_InsufficientMemoryToLoad 152 153 case ErrServiceRateLimit.code(): 154 return commonpb.ErrorCode_RateLimit 155 156 case ErrServiceForceDeny.code(): 157 return commonpb.ErrorCode_ForceDeny 158 159 case ErrIndexNotFound.code(): 160 return commonpb.ErrorCode_IndexNotExist 161 162 case ErrSegmentNotFound.code(): 163 return commonpb.ErrorCode_SegmentNotFound 164 165 case ErrChannelLack.code(): 166 return commonpb.ErrorCode_MetaFailed 167 168 default: 169 return commonpb.ErrorCode_UnexpectedError 170 } 171 } 172 173 func OldCodeToMerr(code commonpb.ErrorCode) error { 174 switch code { 175 case commonpb.ErrorCode_NotReadyServe: 176 return ErrServiceNotReady 177 178 case commonpb.ErrorCode_CollectionNotExists: 179 return ErrCollectionNotFound 180 181 case commonpb.ErrorCode_IllegalArgument: 182 return ErrParameterInvalid 183 184 case commonpb.ErrorCode_NodeIDNotMatch: 185 return ErrNodeNotMatch 186 187 case commonpb.ErrorCode_InsufficientMemoryToLoad, commonpb.ErrorCode_MemoryQuotaExhausted: 188 return ErrServiceMemoryLimitExceeded 189 190 case commonpb.ErrorCode_DiskQuotaExhausted: 191 return ErrServiceDiskLimitExceeded 192 193 case commonpb.ErrorCode_RateLimit: 194 return ErrServiceRateLimit 195 196 case commonpb.ErrorCode_ForceDeny: 197 return ErrServiceForceDeny 198 199 case commonpb.ErrorCode_IndexNotExist: 200 return ErrIndexNotFound 201 202 case commonpb.ErrorCode_SegmentNotFound: 203 return ErrSegmentNotFound 204 205 case commonpb.ErrorCode_MetaFailed: 206 return ErrChannelNotFound 207 208 default: 209 return errUnexpected 210 } 211 } 212 213 func Ok(status *commonpb.Status) bool { 214 return status.GetErrorCode() == commonpb.ErrorCode_Success && status.GetCode() == 0 215 } 216 217 // Error returns a error according to the given status, 218 // returns nil if the status is a success status 219 func Error(status *commonpb.Status) error { 220 if Ok(status) { 221 return nil 222 } 223 224 // use code first 225 code := status.GetCode() 226 if code == 0 { 227 return newMilvusErrorWithDetail(status.GetReason(), status.GetDetail(), Code(OldCodeToMerr(status.GetErrorCode())), false) 228 } 229 return newMilvusErrorWithDetail(status.GetReason(), status.GetDetail(), code, status.GetRetriable()) 230 }