github.com/turingchain2020/turingchain@v1.1.21/client/api/api.go (about) 1 //这个包提供了平行链和主链的统一的访问接口 2 3 package api 4 5 import ( 6 "context" 7 "errors" 8 "sync/atomic" 9 10 "github.com/turingchain2020/turingchain/client" 11 "github.com/turingchain2020/turingchain/queue" 12 "github.com/turingchain2020/turingchain/types" 13 "google.golang.org/grpc" 14 "google.golang.org/grpc/codes" 15 ) 16 17 /* 18 平行链可以访问的有两条链: 19 1. 通过 client.QueueProtocolAPI 事件访问 平行链本身 20 2. 通过 grpc 接口访问主链 21 22 通过 client.QueueProtocolAPI 和 grpc 都可能会产生 网络错误,或者超时的问题 23 这个时候,区块做异常处理的时候需要做一些特殊处理 24 25 接口函数: 26 1. GetBlockByHash 27 2. GetLastBlockHash 28 3. GetRandNum 29 */ 30 31 //ErrAPIEnv api的执行环境出问题,区块执行的时候,遇到这一个的错误需要retry 32 var errAPIEnv = errors.New("ErrAPIEnv") 33 34 //ExecutorAPI 提供给执行器使用的接口 35 //因为合约是主链和平行链通用的,所以,主链和平行链都可以调用这套接口 36 type ExecutorAPI interface { 37 GetBlockByHashes(param *types.ReqHashes) (*types.BlockDetails, error) 38 GetRandNum(param *types.ReqRandHash) ([]byte, error) 39 QueryTx(param *types.ReqHash) (*types.TransactionDetail, error) 40 IsErr() bool 41 } 42 43 type mainChainAPI struct { 44 api client.QueueProtocolAPI 45 errflag int32 46 } 47 48 //New 新建接口 49 func New(api client.QueueProtocolAPI, grpcClient types.TuringchainClient) ExecutorAPI { 50 types.AssertConfig(api) 51 types := api.GetConfig() 52 if types.IsPara() { 53 return newParaChainAPI(api, grpcClient) 54 } 55 return &mainChainAPI{api: api} 56 } 57 58 func (api *mainChainAPI) QueryTx(param *types.ReqHash) (*types.TransactionDetail, error) { 59 data, err := api.api.QueryTx(param) 60 return data, seterr(err, &api.errflag) 61 } 62 63 func (api *mainChainAPI) IsErr() bool { 64 return atomic.LoadInt32(&api.errflag) == 1 65 } 66 67 func (api *mainChainAPI) GetRandNum(param *types.ReqRandHash) ([]byte, error) { 68 msg, err := api.api.Query(param.ExecName, "RandNumHash", param) 69 if err != nil { 70 return nil, seterr(err, &api.errflag) 71 } 72 reply, ok := msg.(*types.ReplyHash) 73 if !ok { 74 return nil, types.ErrTypeAsset 75 } 76 return reply.Hash, nil 77 } 78 79 func (api *mainChainAPI) GetBlockByHashes(param *types.ReqHashes) (*types.BlockDetails, error) { 80 data, err := api.api.GetBlockByHashes(param) 81 return data, seterr(err, &api.errflag) 82 } 83 84 type paraChainAPI struct { 85 api client.QueueProtocolAPI 86 grpcClient types.TuringchainClient 87 errflag int32 88 } 89 90 func newParaChainAPI(api client.QueueProtocolAPI, grpcClient types.TuringchainClient) ExecutorAPI { 91 return ¶ChainAPI{api: api, grpcClient: grpcClient} 92 } 93 94 func (api *paraChainAPI) IsErr() bool { 95 return atomic.LoadInt32(&api.errflag) == 1 96 } 97 98 func (api *paraChainAPI) QueryTx(param *types.ReqHash) (*types.TransactionDetail, error) { 99 data, err := api.grpcClient.QueryTransaction(context.Background(), param) 100 if err != nil { 101 err = errAPIEnv 102 } 103 return data, seterr(err, &api.errflag) 104 } 105 106 func (api *paraChainAPI) GetRandNum(param *types.ReqRandHash) ([]byte, error) { 107 reply, err := api.grpcClient.QueryRandNum(context.Background(), param) 108 if err != nil { 109 err = errAPIEnv 110 return nil, seterr(err, &api.errflag) 111 } 112 return reply.Hash, nil 113 } 114 115 func (api *paraChainAPI) GetBlockByHashes(param *types.ReqHashes) (*types.BlockDetails, error) { 116 data, err := api.grpcClient.GetBlockByHashes(context.Background(), param) 117 if err != nil { 118 err = errAPIEnv 119 } 120 return data, seterr(err, &api.errflag) 121 } 122 123 func seterr(err error, flag *int32) error { 124 if IsGrpcError(err) || IsQueueError(err) { 125 atomic.StoreInt32(flag, 1) 126 } 127 return err 128 } 129 130 //IsGrpcError 判断系统api 错误,还是 rpc 本身的错误 131 func IsGrpcError(err error) bool { 132 if err == nil { 133 return false 134 } 135 if err == errAPIEnv { 136 return true 137 } 138 if grpc.Code(err) == codes.Unknown { 139 return false 140 } 141 return true 142 } 143 144 //IsQueueError 是否是队列错误 145 func IsQueueError(err error) bool { 146 if err == nil { 147 return false 148 } 149 if err == errAPIEnv { 150 return true 151 } 152 if err == queue.ErrQueueTimeout || 153 err == queue.ErrQueueChannelFull || 154 err == queue.ErrIsQueueClosed { 155 return true 156 } 157 return false 158 } 159 160 //IsFatalError 是否是必须停止执行的系统错误 161 func IsFatalError(err error) bool { 162 if err == nil { 163 return false 164 } 165 if err == errAPIEnv { 166 return true 167 } 168 if err == types.ErrConsensusHashErr { 169 return true 170 } 171 return false 172 } 173 174 //IsAPIEnvError 是否是api执行环境的错误 175 func IsAPIEnvError(err error) bool { 176 return IsGrpcError(err) || IsQueueError(err) || IsFatalError(err) 177 }