go.uber.org/cadence@v1.2.9/internal/compatibility/thrift/error.go (about) 1 // Copyright (c) 2021 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package thrift 22 23 import ( 24 "errors" 25 26 apiv1 "github.com/uber/cadence-idl/go/proto/api/v1" 27 "go.uber.org/yarpc/encoding/protobuf" 28 "go.uber.org/yarpc/yarpcerrors" 29 30 "go.uber.org/cadence/.gen/go/shared" 31 "go.uber.org/cadence/internal/common" 32 ) 33 34 func Error(err error) error { 35 status := yarpcerrors.FromError(err) 36 if status == nil || status.Code() == yarpcerrors.CodeOK { 37 return nil 38 } 39 40 switch status.Code() { 41 case yarpcerrors.CodePermissionDenied: 42 return &shared.AccessDeniedError{ 43 Message: status.Message(), 44 } 45 case yarpcerrors.CodeInternal: 46 return &shared.InternalServiceError{ 47 Message: status.Message(), 48 } 49 case yarpcerrors.CodeNotFound: 50 switch details := getErrorDetails(err).(type) { 51 case *apiv1.EntityNotExistsError: 52 return &shared.EntityNotExistsError{ 53 Message: status.Message(), 54 CurrentCluster: &details.CurrentCluster, 55 ActiveCluster: &details.ActiveCluster, 56 } 57 case *apiv1.WorkflowExecutionAlreadyCompletedError: 58 return &shared.WorkflowExecutionAlreadyCompletedError{ 59 Message: status.Message(), 60 } 61 } 62 case yarpcerrors.CodeInvalidArgument: 63 switch getErrorDetails(err).(type) { 64 case nil: 65 return &shared.BadRequestError{ 66 Message: status.Message(), 67 } 68 case *apiv1.QueryFailedError: 69 return &shared.QueryFailedError{ 70 Message: status.Message(), 71 } 72 } 73 case yarpcerrors.CodeAlreadyExists: 74 switch details := getErrorDetails(err).(type) { 75 case *apiv1.CancellationAlreadyRequestedError: 76 return &shared.CancellationAlreadyRequestedError{ 77 Message: status.Message(), 78 } 79 case *apiv1.DomainAlreadyExistsError: 80 return &shared.DomainAlreadyExistsError{ 81 Message: status.Message(), 82 } 83 case *apiv1.WorkflowExecutionAlreadyStartedError: 84 return &shared.WorkflowExecutionAlreadyStartedError{ 85 Message: common.StringPtr(status.Message()), 86 StartRequestId: &details.StartRequestId, 87 RunId: &details.RunId, 88 } 89 } 90 case yarpcerrors.CodeDataLoss: 91 return &shared.InternalDataInconsistencyError{ 92 Message: status.Message(), 93 } 94 case yarpcerrors.CodeFailedPrecondition: 95 switch details := getErrorDetails(err).(type) { 96 case *apiv1.ClientVersionNotSupportedError: 97 return &shared.ClientVersionNotSupportedError{ 98 FeatureVersion: details.FeatureVersion, 99 ClientImpl: details.ClientImpl, 100 SupportedVersions: details.SupportedVersions, 101 } 102 case *apiv1.FeatureNotEnabledError: 103 return &shared.FeatureNotEnabledError{ 104 FeatureFlag: details.FeatureFlag, 105 } 106 case *apiv1.DomainNotActiveError: 107 return &shared.DomainNotActiveError{ 108 Message: status.Message(), 109 DomainName: details.Domain, 110 CurrentCluster: details.CurrentCluster, 111 ActiveCluster: details.ActiveCluster, 112 } 113 } 114 case yarpcerrors.CodeResourceExhausted: 115 switch getErrorDetails(err).(type) { 116 case *apiv1.LimitExceededError: 117 return &shared.LimitExceededError{ 118 Message: status.Message(), 119 } 120 case *apiv1.ServiceBusyError: 121 return &shared.ServiceBusyError{ 122 Message: status.Message(), 123 } 124 } 125 case yarpcerrors.CodeUnknown: 126 return errors.New(status.Message()) 127 } 128 129 // If error does not match anything, return raw yarpc status error 130 // There are some code that casts error to yarpc status to check for deadline exceeded status 131 return status 132 } 133 134 func getErrorDetails(err error) interface{} { 135 details := protobuf.GetErrorDetails(err) 136 if len(details) > 0 { 137 return details[0] 138 } 139 return nil 140 }