Documentation ¶
Overview ¶
Package aceiclient provides an ACEI implementation in Go.
There are 3 clients available:
- socket (unix or TCP)
- local (in memory)
- gRPC
## Socket client
async: the client maintains an internal buffer of a fixed size. when the buffer becomes full, all Async calls will return an error immediately.
sync: the client blocks on 1) enqueuing the Sync request 2) enqueuing the Flush requests 3) waiting for the Flush response
## Local client
async: global mutex is locked during each call (meaning it's not really async!) sync: global mutex is locked during each call
## gRPC client
async: gRPC is synchronous, but an internal buffer of a fixed size is used to store responses and later call callbacks (separate goroutine per response).
sync: waits for all Async calls to complete (essentially what Flush does in the socket client) and calls Sync method.
Index ¶
- func NewGRPCClient(logger log.StandardLogger, addr string, mustConnect bool) (*grpcClient, error)
- func NewLocalClient(logger log.StandardLogger, mtx *gsync.Mutex, app local.Application) (*localClient, error)
- func NewLocalToRemoteProxy(logger log.StandardLogger, mrsh marsha.Marsha, remote Client, ...) (*localToRemoteProxy, error)
- func NewSocketClient(logger log.StandardLogger, addr string, mustConnect bool) (*socketClient, error)
- type Callback
- type Client
- type Creator
- type ExtraCtor
- type LocalClient
- type LocalCreator
- type ReqRes
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewGRPCClient ¶
NewGRPCClient creates a gRPC client, which will connect to addr upon the start. Note Client#Start returns an error if connection is unsuccessful and mustConnect is true.
GRPC calls are synchronous, but some callbacks expect to be called asynchronously (eg. the mempool expects to be able to lock to remove bad txs from cache). To accommodate, we finish each call in its own go-routine, which is expensive, but easy - if you want something better, use the socket protocol! maybe one day, if people really want it, we use grpc streams, but hopefully not :D
func NewLocalClient ¶
func NewLocalClient(logger log.StandardLogger, mtx *gsync.Mutex, app local.Application, ) (*localClient, error)
NewLocalClient creates a local client, which will be directly calling the methods of the given app.
Both Async and Sync methods ignore the given context.Context parameter.
func NewLocalToRemoteProxy ¶
func NewLocalToRemoteProxy(logger log.StandardLogger, mrsh marsha.Marsha, remote Client, blockExtraCtor, txExtraCtor ExtraCtor, ) (*localToRemoteProxy, error)
NewLocalToRemoteProxy creates a localToRemoteProxy, which will proxies all requests to `remote`.
func NewSocketClient ¶
func NewSocketClient(logger log.StandardLogger, addr string, mustConnect bool, ) (*socketClient, error)
NewSocketClient creates a new socket client, which connects to a given address. If mustConnect is true, the client will return an error upon start if it fails to connect.
Types ¶
type Client ¶
type Client interface { ssrv.Service SetResponseCallback(Callback) Error() error // Asynchronous requests FlushAsync(context.Context) (*ReqRes, error) EchoAsync(ctx context.Context, msg string) (*ReqRes, error) InfoAsync(context.Context, types.RequestInfo) (*ReqRes, error) DeliverTxAsync(context.Context, types.RequestDeliverTx) (*ReqRes, error) CheckTxAsync(context.Context, types.RequestCheckTx) (*ReqRes, error) QueryAsync(context.Context, types.RequestQuery) (*ReqRes, error) CommitAsync(context.Context) (*ReqRes, error) InitLedgerAsync(context.Context, types.RequestInitLedger) (*ReqRes, error) BeginBlockAsync(context.Context, types.RequestBeginBlock) (*ReqRes, error) EndBlockAsync(context.Context, types.RequestEndBlock) (*ReqRes, error) ListSnapshotsAsync(context.Context, types.RequestListSnapshots) (*ReqRes, error) OfferSnapshotAsync(context.Context, types.RequestOfferSnapshot) (*ReqRes, error) LoadSnapshotChunkAsync(context.Context, types.RequestLoadSnapshotChunk) (*ReqRes, error) ApplySnapshotChunkAsync(context.Context, types.RequestApplySnapshotChunk) (*ReqRes, error) // Synchronous requests FlushSync(context.Context) error EchoSync(ctx context.Context, msg string) (*types.ResponseEcho, error) InfoSync(context.Context, types.RequestInfo) (*types.ResponseInfo, error) DeliverTxSync(context.Context, types.RequestDeliverTx) (*types.ResponseDeliverTx, error) CheckTxSync(context.Context, types.RequestCheckTx) (*types.ResponseCheckTx, error) QuerySync(context.Context, types.RequestQuery) (*types.ResponseQuery, error) CommitSync(context.Context) (*types.ResponseCommit, error) InitLedgerSync(context.Context, types.RequestInitLedger) (*types.ResponseInitLedger, error) BeginBlockSync(context.Context, types.RequestBeginBlock) (*types.ResponseBeginBlock, error) EndBlockSync(context.Context, types.RequestEndBlock) (*types.ResponseEndBlock, error) ListSnapshotsSync(context.Context, types.RequestListSnapshots) (*types.ResponseListSnapshots, error) OfferSnapshotSync(context.Context, types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) LoadSnapshotChunkSync(context.Context, types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) ApplySnapshotChunkSync(context.Context, types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) }
Client defines an interface for an ACEI client.
All `Async` methods return a `ReqRes` object and an error. All `Sync` methods return the appropriate protobuf ResponseXxx struct and an error.
NOTE these are client errors, eg. ACEI socket connectivity issues. Application-related errors are reflected in response via ACEI error codes and logs.
type Creator ¶
Creator creates new ACEI clients.
func NewRemoteCreator ¶
NewRemoteCreator returns a Creator for the given address (e.g. "192.168.0.1") and transport (e.g. "tcp"). Set mustConnect to true if you want the client to connect before reporting success.
type LocalClient ¶
type LocalClient interface { Error() error Flush(context.Context) error Echo(ctx context.Context, msg string) (*types.ResponseEcho, error) Info(context.Context, *types.RequestInfo) (*types.ResponseInfo, error) DeliverTx(context.Context, *local.RequestNativeDeliverTx) (*types.ResponseDeliverTx, error) CheckTx(context.Context, *local.RequestNativeCheckTx) (*local.ResponseNativeCheckTx, error) Query(context.Context, *types.RequestQuery) (*types.ResponseQuery, error) Commit(context.Context) (*types.ResponseCommit, error) InitLedger(context.Context, *local.RequestNativeInitLedger) (*local.ResponseNativeInitLedger, error) BeginBlock(context.Context, *local.RequestNativeBeginBlock) (*types.ResponseBeginBlock, error) EndBlock(context.Context, *types.RequestEndBlock) (*local.ResponseNativeEndBlock, error) ListSnapshots(context.Context, *types.RequestListSnapshots) (*types.ResponseListSnapshots, error) OfferSnapshot(context.Context, *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) LoadSnapshotChunk(context.Context, *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) ApplySnapshotChunk(context.Context, *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) }
LocalClient interface is a process-local version of the Client interface.
All methods take a pointer argument and return a pointer to avoid copying, some methods also take a RequestNativeXxx argument and/or return a ResponseNativeXxx argument, which directly use Go-native types form go-doubl instead of corresponding Protocol Buffers types.
Application-related errors are reflected in response via ACEI error codes and logs.
type LocalCreator ¶
type LocalCreator func(log.StandardLogger) (LocalClient, error)
LocalCreator creates new local ACEI clients.
func NewLocalCreator ¶
func NewLocalCreator(logger log.StandardLogger, app local.Application) LocalCreator
NewLocalCreator returns a Creator for the given Application, which will be running locally.
type ReqRes ¶
type ReqRes struct { *types.Request *sync.WaitGroup *types.Response // Not set atomically, so be sure to use WaitGroup. // contains filtered or unexported fields }
func (*ReqRes) GetCallback ¶
GetCallback returns the configured callback of the ReqRes object which may be nil. Note, it is not safe to concurrently call this in cases where it is marked done and SetCallback is called before calling GetCallback as that will invoke the callback twice and create a potential race condition.
func (*ReqRes) InvokeCallback ¶
func (r *ReqRes) InvokeCallback()
InvokeCallback invokes a thread-safe execution of the configured callback if non-nil.
func (*ReqRes) SetCallback ¶
Sets sets the callback. If reqRes is already done, it will call the cb immediately. Note, reqRes.cb should not change if reqRes.done and only one callback is supported.