github.com/lazyledger/lazyledger-core@v0.35.0-dev.0.20210613111200-4c651f053571/abci/client/client.go (about) 1 package abcicli 2 3 import ( 4 "context" 5 6 "sync" 7 8 "github.com/lazyledger/lazyledger-core/abci/types" 9 "github.com/lazyledger/lazyledger-core/libs/service" 10 tmsync "github.com/lazyledger/lazyledger-core/libs/sync" 11 ) 12 13 //go:generate mockery --case underscore --name Client 14 15 // Client defines an interface for an ABCI client. 16 // 17 // All `Async` methods return a `ReqRes` object and an error. 18 // All `Sync` methods return the appropriate protobuf ResponseXxx struct and an error. 19 // 20 // NOTE these are client errors, eg. ABCI socket connectivity issues. 21 // Application-related errors are reflected in response via ABCI error codes 22 // and logs. 23 type Client interface { 24 service.Service 25 26 SetResponseCallback(Callback) 27 Error() error 28 29 // Asynchronous requests 30 FlushAsync(context.Context) (*ReqRes, error) 31 EchoAsync(ctx context.Context, msg string) (*ReqRes, error) 32 InfoAsync(context.Context, types.RequestInfo) (*ReqRes, error) 33 DeliverTxAsync(context.Context, types.RequestDeliverTx) (*ReqRes, error) 34 CheckTxAsync(context.Context, types.RequestCheckTx) (*ReqRes, error) 35 QueryAsync(context.Context, types.RequestQuery) (*ReqRes, error) 36 CommitAsync(context.Context) (*ReqRes, error) 37 InitChainAsync(context.Context, types.RequestInitChain) (*ReqRes, error) 38 BeginBlockAsync(context.Context, types.RequestBeginBlock) (*ReqRes, error) 39 EndBlockAsync(context.Context, types.RequestEndBlock) (*ReqRes, error) 40 ListSnapshotsAsync(context.Context, types.RequestListSnapshots) (*ReqRes, error) 41 OfferSnapshotAsync(context.Context, types.RequestOfferSnapshot) (*ReqRes, error) 42 LoadSnapshotChunkAsync(context.Context, types.RequestLoadSnapshotChunk) (*ReqRes, error) 43 ApplySnapshotChunkAsync(context.Context, types.RequestApplySnapshotChunk) (*ReqRes, error) 44 PreprocessTxsAsync(context.Context, types.RequestPreprocessTxs) (*ReqRes, error) 45 46 // Synchronous requests 47 FlushSync(context.Context) error 48 EchoSync(ctx context.Context, msg string) (*types.ResponseEcho, error) 49 InfoSync(context.Context, types.RequestInfo) (*types.ResponseInfo, error) 50 DeliverTxSync(context.Context, types.RequestDeliverTx) (*types.ResponseDeliverTx, error) 51 CheckTxSync(context.Context, types.RequestCheckTx) (*types.ResponseCheckTx, error) 52 QuerySync(context.Context, types.RequestQuery) (*types.ResponseQuery, error) 53 CommitSync(context.Context) (*types.ResponseCommit, error) 54 InitChainSync(context.Context, types.RequestInitChain) (*types.ResponseInitChain, error) 55 BeginBlockSync(context.Context, types.RequestBeginBlock) (*types.ResponseBeginBlock, error) 56 EndBlockSync(context.Context, types.RequestEndBlock) (*types.ResponseEndBlock, error) 57 ListSnapshotsSync(context.Context, types.RequestListSnapshots) (*types.ResponseListSnapshots, error) 58 OfferSnapshotSync(context.Context, types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) 59 LoadSnapshotChunkSync(context.Context, types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) 60 ApplySnapshotChunkSync(context.Context, types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) 61 PreprocessTxsSync(context.Context, types.RequestPreprocessTxs) (*types.ResponsePreprocessTxs, error) 62 } 63 64 type Callback func(*types.Request, *types.Response) 65 66 //---------------------------------------- 67 68 type ReqRes struct { 69 *types.Request 70 *sync.WaitGroup 71 *types.Response // Not set atomically, so be sure to use WaitGroup. 72 73 mtx tmsync.Mutex 74 done bool // Gets set to true once *after* WaitGroup.Done(). 75 cb func(*types.Response) // A single callback that may be set. 76 } 77 78 func NewReqRes(req *types.Request) *ReqRes { 79 return &ReqRes{ 80 Request: req, 81 WaitGroup: waitGroup1(), 82 Response: nil, 83 84 done: false, 85 cb: nil, 86 } 87 } 88 89 // Sets the callback for this ReqRes atomically. 90 // If reqRes is already done, calls cb immediately. 91 // NOTE: reqRes.cb should not change if reqRes.done. 92 // NOTE: only one callback is supported. 93 func (reqRes *ReqRes) SetCallback(cb func(res *types.Response)) { 94 reqRes.mtx.Lock() 95 96 if reqRes.done { 97 reqRes.mtx.Unlock() 98 cb(reqRes.Response) 99 return 100 } 101 102 reqRes.cb = cb 103 reqRes.mtx.Unlock() 104 } 105 106 func (reqRes *ReqRes) GetCallback() func(*types.Response) { 107 reqRes.mtx.Lock() 108 defer reqRes.mtx.Unlock() 109 return reqRes.cb 110 } 111 112 // NOTE: it should be safe to read reqRes.cb without locks after this. 113 func (reqRes *ReqRes) SetDone() { 114 reqRes.mtx.Lock() 115 reqRes.done = true 116 reqRes.mtx.Unlock() 117 } 118 119 func waitGroup1() (wg *sync.WaitGroup) { 120 wg = &sync.WaitGroup{} 121 wg.Add(1) 122 return 123 }