Skip to content

abci/client: simplify client interface#7607

Merged
creachadair merged 3 commits intomasterfrom
mjf/desync
Jan 19, 2022
Merged

abci/client: simplify client interface#7607
creachadair merged 3 commits intomasterfrom
mjf/desync

Conversation

@creachadair
Copy link

@creachadair creachadair commented Jan 15, 2022

As we discussed at the ABCI++ meeting, the rollout in v0.36 is an ideal time to clean up some infelicities in the original implementation. This is a first step toward that cleanup. We will still have to address Flush, CommitTx, and DeliverTx separately, but getting the easy cases out of the way will help keep those diffs smaller.

N.B.: The diff in grpc_client.go is large, but less complicated than it looks. It folds the sync/async versions back together, strips out the unnecessary support code, and updates the names. The rename makes the diff look hairier than it should be.

This change has two main effects:

  1. Remove most of the Async methods from the abci.Client interface.
    Remaining are FlushAsync, CommitTxAsync, and DeliverTxAsync.

  2. Rename the synchronous methods to remove the "Sync" suffix.

The rest of the change is updating the implementations, subsets, and mocks of
the interface, along with the call sites that point to them.

TODO before after merge:

Copy link
Contributor

@tac0turtle tac0turtle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

love to see this being cleanup. Before merging might want to do a sanity check with @ebuchman, I believe he may know why this exists.

Im for this change and in the sdk we only use the local client, so not sure where all this came in

@creachadair creachadair force-pushed the mjf/desync branch 3 times, most recently from f918b4f to 0f65c93 Compare January 16, 2022 21:49
Copy link
Contributor

@cmwaters cmwaters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM pending a check from @ebuchman or @milosevic

@@ -33,35 +33,24 @@ type Client interface {

// Asynchronous requests
FlushAsync(context.Context) (*ReqRes, error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we still need this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might not. It's called in the mempool and the proxy app. It might be we could get rid of those, or swap them to synchronous, but I didn't want to expand this change with functional changes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah makes sense to tackle this as a different issue/PR

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this gets used in the mempool right? Is it possible (in a follow up PR of course) to modify the usage so we can call CheckTx instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I tried this, sort of naively, and I think it's possible, but the impact on the mempool is pretty good (mostly because there are a bunch of tests that do assertions/etc. via the callback. I think the best path forward would be to merge this, and then write a shim in the mempool package that does the switch and try and go from there.

@creachadair creachadair force-pushed the mjf/desync branch 8 times, most recently from 64a95a6 to 3089ceb Compare January 19, 2022 02:37
@cmwaters
Copy link
Contributor

FYI, I followed up with Ethan on slack and he had this response:

this has never been benchmarked but jaes original intention was performance, thinking especially about out-of-process apps. the idea being that txs could quickly sent to the app without having to wait for response
i think its only used for delivertx and checktx. the whole mempool was built around it. does it even work for in-process apps i dont rememver? i think so
so conceivably could be a performance hit in the mempool to use sync abci instead but its also possible the server side abci and sdk arent even making use of it properly and so its all moot lol

Copy link
Contributor

@williambanfield williambanfield left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me very happy. Not sure I understand the distinction between Flush vs FlushAsync. Didn't look at the mocks.


func (cli *socketClient) EchoSync(ctx context.Context, msg string) (*types.ResponseEcho, error) {
func (cli *socketClient) Echo(ctx context.Context, msg string) (*types.ResponseEcho, error) {
reqres, err := cli.queueRequestAndFlushSync(ctx, types.ToRequestEcho(msg))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we rename these as well -> queueRequestAndFlush?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In re: Flush vs. FlushAsync. As far as I can tell, there is no difference, but when I tried to get rid of FlushAsync it metastasized. I suspect there is a kernel of simplicity inside that we could use. (Flush appears to be primarily an artifact of the socket client anyway, cf. #6994).

In re: Plumbing methods. Sure, done. But it's harder to be systematic about those.

gofmt -r 'queueRequestAndFlushSync->queueRequestAndFlush' -w  abci/client/socket_client.go

@creachadair creachadair force-pushed the mjf/desync branch 2 times, most recently from defedc2 to 825aca7 Compare January 19, 2022 16:24
@creachadair
Copy link
Author

FYI, I followed up with Ethan on slack and he had this response:

this has never been benchmarked but jaes original intention was performance, thinking especially about out-of-process apps. the idea being that txs could quickly sent to the app without having to wait for response
i think its only used for delivertx and checktx. the whole mempool was built around it. does it even work for in-process apps i dont rememver? i think so
so conceivably could be a performance hit in the mempool to use sync abci instead but its also possible the server side abci and sdk arent even making use of it properly and so its all moot lol

I agree this is something worth measuring. At the moment I think neither in-process nor out-of-process applications can practically benefit from concurrency here: Even for CheckTx, the socket protocol requires head-of-line blocking because requests cannot be interleaved. And for in-process all client requests share a global mutex. Both of those are issues I think we should address—for performance, certainly, but also to make the control flow easier to understand.

For now, though, I don't think these client-side changes can have any material effect on the performance (in either direction).

This change has two main effects:

1. Remove most of the Async methods from the abci.Client interface.
   Remaining are FlushAsync, CommitTxAsync, and DeliverTxAsync.

2. Rename the synchronous methods to remove the "Sync" suffix.

The rest of the change is updating the implementations, subsets, and mocks of
the interface, along with the call sites that point to them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants