|
package abciclient
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/tendermint/tendermint/abci/types"
|
|
"github.com/tendermint/tendermint/libs/log"
|
|
"github.com/tendermint/tendermint/libs/service"
|
|
)
|
|
|
|
const (
|
|
dialRetryIntervalSeconds = 3
|
|
echoRetryIntervalSeconds = 1
|
|
)
|
|
|
|
//go:generate ../../scripts/mockery_generate.sh Client
|
|
|
|
// Client defines an interface for an ABCI client.
|
|
//
|
|
// All methods return the appropriate protobuf ResponseXxx struct and
|
|
// an error.
|
|
//
|
|
// NOTE these are client errors, eg. ABCI socket connectivity issues.
|
|
// Application-related errors are reflected in response via ABCI error codes
|
|
// and logs.
|
|
type Client interface {
|
|
service.Service
|
|
|
|
Error() error
|
|
|
|
Flush(context.Context) error
|
|
Echo(ctx context.Context, msg string) (*types.ResponseEcho, error)
|
|
Info(context.Context, types.RequestInfo) (*types.ResponseInfo, error)
|
|
CheckTx(context.Context, types.RequestCheckTx) (*types.ResponseCheckTx, error)
|
|
Query(context.Context, types.RequestQuery) (*types.ResponseQuery, error)
|
|
Commit(context.Context) (*types.ResponseCommit, error)
|
|
InitChain(context.Context, types.RequestInitChain) (*types.ResponseInitChain, error)
|
|
PrepareProposal(context.Context, types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error)
|
|
ProcessProposal(context.Context, types.RequestProcessProposal) (*types.ResponseProcessProposal, error)
|
|
ExtendVote(context.Context, types.RequestExtendVote) (*types.ResponseExtendVote, error)
|
|
VerifyVoteExtension(context.Context, types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error)
|
|
FinalizeBlock(context.Context, types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, 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)
|
|
}
|
|
|
|
//----------------------------------------
|
|
|
|
// NewClient returns a new ABCI client of the specified transport type.
|
|
// It returns an error if the transport is not "socket" or "grpc"
|
|
func NewClient(logger log.Logger, addr, transport string, mustConnect bool) (Client, error) {
|
|
switch transport {
|
|
case "socket":
|
|
return NewSocketClient(logger, addr, mustConnect), nil
|
|
case "grpc":
|
|
return NewGRPCClient(logger, addr, mustConnect), nil
|
|
default:
|
|
return nil, fmt.Errorf("unknown abci transport %s", transport)
|
|
}
|
|
}
|
|
|
|
type requestAndResponse struct {
|
|
*types.Request
|
|
*types.Response
|
|
|
|
mtx sync.Mutex
|
|
signal chan struct{}
|
|
}
|
|
|
|
func makeReqRes(req *types.Request) *requestAndResponse {
|
|
return &requestAndResponse{
|
|
Request: req,
|
|
Response: nil,
|
|
signal: make(chan struct{}),
|
|
}
|
|
}
|
|
|
|
// markDone marks the ReqRes object as done.
|
|
func (r *requestAndResponse) markDone() {
|
|
r.mtx.Lock()
|
|
defer r.mtx.Unlock()
|
|
|
|
close(r.signal)
|
|
}
|