github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/bft/abci/client/client.go (about) 1 package abcicli 2 3 import ( 4 "sync" 5 6 abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" 7 "github.com/gnolang/gno/tm2/pkg/service" 8 ) 9 10 // Client defines an interface for an ABCI client. 11 // All `Async` methods return a `ReqRes` object. 12 // All `Sync` methods return the appropriate protobuf ResponseXxx struct and an error. 13 // Note these are client errors, eg. ABCI socket connectivity issues. 14 // Application-related errors are reflected in response via ABCI error codes and logs. 15 type Client interface { 16 service.Service 17 18 SetResponseCallback(Callback) 19 Error() error 20 21 FlushAsync() *ReqRes 22 EchoAsync(msg string) *ReqRes 23 InfoAsync(abci.RequestInfo) *ReqRes 24 SetOptionAsync(abci.RequestSetOption) *ReqRes 25 DeliverTxAsync(abci.RequestDeliverTx) *ReqRes 26 CheckTxAsync(abci.RequestCheckTx) *ReqRes 27 QueryAsync(abci.RequestQuery) *ReqRes 28 CommitAsync() *ReqRes 29 InitChainAsync(abci.RequestInitChain) *ReqRes 30 BeginBlockAsync(abci.RequestBeginBlock) *ReqRes 31 EndBlockAsync(abci.RequestEndBlock) *ReqRes 32 33 FlushSync() error 34 EchoSync(msg string) (abci.ResponseEcho, error) 35 InfoSync(abci.RequestInfo) (abci.ResponseInfo, error) 36 SetOptionSync(abci.RequestSetOption) (abci.ResponseSetOption, error) 37 DeliverTxSync(abci.RequestDeliverTx) (abci.ResponseDeliverTx, error) 38 CheckTxSync(abci.RequestCheckTx) (abci.ResponseCheckTx, error) 39 QuerySync(abci.RequestQuery) (abci.ResponseQuery, error) 40 CommitSync() (abci.ResponseCommit, error) 41 InitChainSync(abci.RequestInitChain) (abci.ResponseInitChain, error) 42 BeginBlockSync(abci.RequestBeginBlock) (abci.ResponseBeginBlock, error) 43 EndBlockSync(abci.RequestEndBlock) (abci.ResponseEndBlock, error) 44 } 45 46 // ---------------------------------------- 47 48 type Callback func(abci.Request, abci.Response) 49 50 // ---------------------------------------- 51 52 type ReqRes struct { 53 abci.Request 54 wg *sync.WaitGroup 55 56 mtx sync.Mutex 57 abci.Response 58 cb func(abci.Response) // A single callback that may be set. 59 } 60 61 func NewReqRes(req abci.Request) *ReqRes { 62 return &ReqRes{ 63 Request: req, 64 wg: waitGroup1(), 65 Response: nil, 66 67 cb: nil, 68 } 69 } 70 71 // Sets the callback for this ReqRes atomically. 72 // If reqRes is already done, calls cb immediately. 73 // NOTE: reqRes.cb should not change if reqRes.done. 74 // NOTE: only one callback is supported. 75 func (reqRes *ReqRes) SetCallback(cb func(res abci.Response)) { 76 reqRes.mtx.Lock() 77 78 if reqRes.Response != nil { 79 reqRes.mtx.Unlock() 80 cb(reqRes.Response) 81 return 82 } 83 84 reqRes.cb = cb 85 reqRes.mtx.Unlock() 86 } 87 88 func (reqRes *ReqRes) GetCallback() func(abci.Response) { 89 reqRes.mtx.Lock() 90 defer reqRes.mtx.Unlock() 91 return reqRes.cb 92 } 93 94 // Wait will wait until SetResponse() is called. 95 func (reqRes *ReqRes) Wait() { 96 reqRes.wg.Wait() 97 } 98 99 func (reqRes *ReqRes) SetResponse(res abci.Response) { 100 reqRes.mtx.Lock() 101 if reqRes.Response != nil { 102 panic("should not happen") 103 } 104 reqRes.Response = res 105 reqRes.mtx.Unlock() 106 107 reqRes.wg.Done() 108 } 109 110 // NOTE: it should be safe to read reqRes.cb without locks after this. 111 func (reqRes *ReqRes) Done() { 112 // Finally, release the hounds. 113 reqRes.wg.Done() 114 } 115 116 func waitGroup1() (wg *sync.WaitGroup) { 117 wg = &sync.WaitGroup{} 118 wg.Add(1) 119 return 120 }