Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADR 009: ChainEndpoint/ChainHandle Consolidation #2108

Merged

Conversation

plafer
Copy link
Contributor

@plafer plafer commented Apr 19, 2022

Description

This PR proposes ADR 8, which aims to reduce the code duplication between the ChainEndpoint and ChainHandle traits.


PR author checklist:

  • Added changelog entry, using unclog.
  • Added tests: integration (for Hermes) or unit/mock tests (for modules).
  • Linked to GitHub issue.
  • Updated code comments and documentation (e.g., docs/).

Reviewer checklist:

  • Reviewed Files changed in the GitHub PR explorer.
  • Manually tested (in case integration/unit/mock tests are absent).

@plafer
Copy link
Contributor Author

plafer commented Apr 19, 2022

Please let me know if you can think of better names for ChainBase and unroll_template.

@plafer plafer added this to the v0.14.0 milestone Apr 20, 2022
@mzabaluev
Copy link
Contributor

In my understanding, ChainEndpoint is the extension point to enable runtime backends for different chains (in the future).
ChainHandle is used to build utility on the API client side, such as mocks for testing, statistics middleware, and the like.

One potential concern with this change is that it may introduce unnecessary coupling between the client side and the runtime mechanics. For example, in a future async rewrite we might choose to convert components to async piecemeal or even leave some of them synchronous. Use of a common trait would make that process unnecessarily complicated.

That said, I'm all for reducing the surface area of the traits by deduplicating methods, using auxiliary data types, etc.

@adizere
Copy link
Member

adizere commented Apr 21, 2022

In my understanding, ChainEndpoint is the extension point to enable runtime backends for different chains (in the future).
ChainHandle is used to build utility on the API client side, such as mocks for testing, statistics middleware, and the like.

This is a very good point. It is highlighted also in our of older ADRs (005). The runtime backends are described here. The API client side can also be seen as a "relayer application" which uses the ChainHandle.

One advantage of this 2-sided architecture is that we can customize handlers (relayer application logic) independently of runtimes. A concrete example is in the caching layer implementation, which was added as a custom chain handle.

@adizere
Copy link
Member

adizere commented Apr 21, 2022

One more input we should take into account in the redesign of Runtime/Handlers is the need for supporting parallel queries in the runtime. The problem is as follows:

Whenever a relayer object (ForeignClient, Connection, RelayPath, etc) wants to assemble a message (such as a client update message), it needs to do certain queries on both the source and destination chain. Currently, each such query is serialized via the Handle -> crossbeam -> Runtime (blocking) interface. This enforces that all relayer objects must wait on each other when they want to query a certain chain, a limitation that likely affects performance.

Can we fulfil this requirement with the proposed redesign, or can we accommodate it?

@plafer
Copy link
Contributor Author

plafer commented Apr 21, 2022

Good point @mzabaluev. How I see it, nothing needs to change in the ADR other than having both ChainEndpoint and ChainHandle have some ChainBase as supertrait. This will facilitate further changes we expect that would have these traits' interface diverge.

@adizere IIUC, you're referring to the problem that ChainRuntime::run() takes one message at a time out of the channel, delegates the network request to the inner ChainEndpoint, and waits until it gets the response back until it starts processing the next item in the channel. That to me calls for refactoring the Runtime to use async features, and falls out of the scope of this ADR. I will say though that I don't foresee the changes I'm proposing here to make this future async refactor more difficult.

@mzabaluev
Copy link
Contributor

@adizere When we get an async tendermint-rs, we could start with converting the runtime (and ChainEndpoint) to async. If we choose to not do the same for the ChainHandle APIs at that point, the common base trait would be a hindrance.

```


### Procedural macro
Copy link
Member

Choose a reason for hiding this comment

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

While I agree that implementing these query_ methods is fairly repetitive and boilerplaty, I would rather not introduce a macro-based solution at this stage. Let's keep the code simple and readable and only fallback on macros if absolutely necessary.

@adizere adizere removed this from the v0.14.0 milestone Apr 25, 2022
@adizere
Copy link
Member

adizere commented Apr 25, 2022

Meta: removed this PR from milestone 0.14 (we're using milestones for issues, not PRs). It's OK to push this work into next release train (0.15).

## Decision

### Query methods parameters
There are currently discrepancies between how methods take their arguments. Some take a `request` object, and others take fine-grained arguments that will be used to build a `request` object in the implementation of the method. For example, `query_consensus_state()` takes arguments that will be used to build a request object, whereas `query_consensus_states()` takes a request object directly.
Copy link
Member

Choose a reason for hiding this comment

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

I think most of the places where we're taking a request object is because the underlying RPC method relies on gRPC. Where we lack Request* it's often because we rely on ABCI (called rcp_client) underlying transport.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As discussed with @romac, this ADR would have each method have a domain Request* type, irrespective of if it ends up using RPC, gRPC, etc, effectively abstracting that away.

@plafer plafer changed the title ADR 008: ChainEndpoint/ChainHandle Consolidation ADR 009: ChainEndpoint/ChainHandle Consolidation Apr 28, 2022
Copy link
Member

@adizere adizere left a comment

Choose a reason for hiding this comment

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

Feel free to merge Philippe. Nice consolidation!

@plafer plafer merged commit f17677d into master May 3, 2022
@plafer plafer deleted the plafer/adr-008-ChainEndpoint-ChainHandle-consolidation branch May 3, 2022 12:54
hu55a1n1 pushed a commit to hu55a1n1/hermes that referenced this pull request Sep 13, 2022
* adr 8 proposal

* updated README

* Update ADR given comments
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.

4 participants