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

[request-response] Refine success & error reporting for inbound requests. #1867

Merged
merged 10 commits into from Dec 7, 2020

Conversation

romanb
Copy link
Contributor

@romanb romanb commented Nov 30, 2020

This PR is a follow-up to #1863 and #1860. Supersedes #1863.

Motivation

At the moment one can neither get confirmation when a response has been sent on the underlying transport, nor is one aware of response omissions. The latter was originally intended as a feature for support of one-way protocols, which seems like a bad idea in hindsight. The lack of a notification for sent responses may prohibit implementation of some request-response protocols that need to ensure a happens-before relation between sending a response and a subsequent request, besides possible uses for collecting statistics.

Change Summary

  • Dropped support for "one-way" request-response protocols.
  • New InboundFailure::ResponseOmission variant.
  • Removed InboundFailure::ConnectionClosed variant.
  • RequestResponse::send_response() now returns a Result, allowing early detection of failed inbound requests due to timeout or a closed connection.
  • New RequestResponseEvent::ResponseSent variant, emitted when the response has been successfully written on the underlying transport connection.

Discussion

Even with these changes, there is no active notification for failed inbound requests as a result of connections unexpectedly closing, as is the case for outbound requests. Instead, for pending inbound requests this scenario can be identified, if necessary, either through errors returned on send_response or by the absence of both InboundFailure and ResponseSent events for a particular previously received request. Interest in this situation is not expected to be common and would otherwise require explicitly tracking all inbound requests in the RequestResponse behaviour just to actively report ConnectionClosed for each pending inbound request in that scenario, which would be a pity. Notably RequestResponse::send_response now also synchronously returns an error if the inbound upgrade handling the request has been aborted, due to timeout or closing of the connection, giving more options for graceful error handling for inbound requests. It is also noteworthy that client code that does not call send_response() will now necessarily receive a InboundFailure::ResponseOmission, so except for the case where a connection closes just after send_response() succeeded, client code is usually bound to notice a closed connection already on send_response().

Note: This PR does not prohibit (re-)adding InboundFailure::ConnectionClosed and dedicated inbound request tracking in the future, and neither would doing so make any changes proposed here obsolete. The above discussion is just to expand on why I think the need for doing so becomes even less likely.

Throttled Wrapper Credit Grants

As an aside, the Throttled wrapper now no longer emits inbound or outbound error events occurring in the context of sending credit requests or responses. This is in addition to not emitting ResponseSent events for ACK responses of credit grants. I think the credit requests and responses, including errors, should be completely opaque to the user. If credit messages keep failing, the effect on the public API should merely be that of back-pressure due to running out of credit.

At the moment one can neither get confirmation when a
response has been sent on the underlying transport, nor
is one aware of response omissions. The latter was
originally intended as a feature for support of
one-way protocols, which seems like a bad idea in
hindsight. The lack of notification for sent
responses may prohibit implementation of some
request-response protocols that need to ensure
a happens-before relation between sending a
response and a subsequent request, besides uses
for collecting statistics.

Even with these changes, there is no active notification
for failed inbound requests as a result of connections
unexpectedly closing, as is the case for outbound requests.
Instead, for pending inbound requests this scenario
can be identified if necessary by the absense of both
`InboundFailure` and `ResponseSent` events for a particular
previously received request. Interest in this situation is
not expected to be common and would otherwise require
explicitly tracking all inbound requests in the `RequestResponse`
behaviour, which would be a pity. `RequestResponse::send_response`
now also synchronously returns an error if the inbound upgrade
handling the request has been aborted, due to timeout or
closing of the connection, giving more options for graceful
error handling for inbound requests.

As an aside, the `Throttled` wrapper now no longer emits
inbound or outbound error events occurring in the context
of sending credit requests or responses. This is in addition
to not emitting `ResponseSent` events for ACK responses of
credit grants.
@romanb romanb requested a review from mxinden November 30, 2020 15:11
Copy link
Member

@mxinden mxinden left a comment

Choose a reason for hiding this comment

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

Thanks for putting more thoughts into this.

Dropped support for "one-way" request-response protocols.

I guess requiring an (empty) response is not much of a performance penalty but only a user experience loss, given the already existing overhead of a connection oriented protocol (TCP) and the multiplexing layer on top.

New InboundFailure::ResponseOmission variant.

I imagine this to be helpful when debugging.

Removed InboundFailure::ConnectionClosed variant.

👍

RequestResponse::send_response() now returns a Result, allowing early detection of failed inbound requests due to timeout or a closed connection.

I am in favor of this fast feedback.

New RequestResponseEvent::ResponseSent variant, emitted when the response has been successfully written on the underlying transport connection.

👍

protocols/request-response/src/lib.rs Outdated Show resolved Hide resolved
protocols/request-response/src/throttled.rs Outdated Show resolved Hide resolved
Co-authored-by: Max Inden <mail@max-inden.de>
romanb and others added 2 commits December 3, 2020 14:44
In order to avoid emitting events relating to credit grants or acks
on the public API. The public API should only emit events relating
to the actual requests and responses sent by client code.
@romanb romanb force-pushed the request-response-inbound-refine branch from a087eb7 to 3c352cb Compare December 3, 2020 13:51
Copy link
Member

@mxinden mxinden left a comment

Choose a reason for hiding this comment

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

After various attempts, I didn't find a better way to be certain about the events emitted by the API than to track the request IDs relating to pending credit requests or responses. Thereby I also merged the credit_messages top-level hashmap keyed by PeerId into the peer_info map, as the former entries never live longer than the latter, aggregating all credit information with a peer for sending and receiving in the structs SendBudget and ReceiveBudget. I hope this is a small improvement. See 3c352cb.

Thanks for tackling this. Changes look good to me. I am in favor of merging credit_messages into peer_info.

@mxinden
Copy link
Member

mxinden commented Dec 7, 2020

Any objects to merging this pull request? In case there are none, I would merge and release today and update paritytech/substrate#7478.

@romanb
Copy link
Contributor Author

romanb commented Dec 7, 2020

I think I just have some minor pending cleanup to do today. I will do that today and then merge and release.

@romanb romanb merged commit 3edc467 into libp2p:master Dec 7, 2020
@romanb romanb deleted the request-response-inbound-refine branch December 7, 2020 12:07
@romanb
Copy link
Contributor Author

romanb commented Dec 7, 2020

Before preparing a new release I'd like to get a patch for #1872 in as well, hopefully still today.

AgeManning added a commit to sigp/rust-libp2p that referenced this pull request Dec 16, 2020
* Update rustls requirement from 0.18.0 to 0.19.0 (libp2p#1852)

Updates the requirements on [rustls](https://github.com/ctz/rustls) to permit the latest version.
- [Release notes](https://github.com/ctz/rustls/releases)
- [Changelog](https://github.com/ctz/rustls/blob/main/OLDCHANGES.md)
- [Commits](rustls/rustls@v/0.18.0...v/0.19.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Prepare libp2p-websocket-0.26.1

* Update top-level libp2p-websocket patch version.

* [request-response] Refine success & error reporting for inbound requests. (libp2p#1867)

* Refine error reporting for inbound request handling.

At the moment one can neither get confirmation when a
response has been sent on the underlying transport, nor
is one aware of response omissions. The latter was
originally intended as a feature for support of
one-way protocols, which seems like a bad idea in
hindsight. The lack of notification for sent
responses may prohibit implementation of some
request-response protocols that need to ensure
a happens-before relation between sending a
response and a subsequent request, besides uses
for collecting statistics.

Even with these changes, there is no active notification
for failed inbound requests as a result of connections
unexpectedly closing, as is the case for outbound requests.
Instead, for pending inbound requests this scenario
can be identified if necessary by the absense of both
`InboundFailure` and `ResponseSent` events for a particular
previously received request. Interest in this situation is
not expected to be common and would otherwise require
explicitly tracking all inbound requests in the `RequestResponse`
behaviour, which would be a pity. `RequestResponse::send_response`
now also synchronously returns an error if the inbound upgrade
handling the request has been aborted, due to timeout or
closing of the connection, giving more options for graceful
error handling for inbound requests.

As an aside, the `Throttled` wrapper now no longer emits
inbound or outbound error events occurring in the context
of sending credit requests or responses. This is in addition
to not emitting `ResponseSent` events for ACK responses of
credit grants.

* Update protocols/request-response/src/lib.rs

Co-authored-by: Max Inden <mail@max-inden.de>

* Address some minor clippy warnings. (libp2p#1868)

* Track pending credit request IDs.

In order to avoid emitting events relating to credit grants or acks
on the public API. The public API should only emit events relating
to the actual requests and responses sent by client code.

* Small cleanup

* Cleanup

* Update versions and changelogs.

* Unreleased

Co-authored-by: Max Inden <mail@max-inden.de>

* core/benches: Add rudimentary benchmark for PeerId::from_bytes and clone (libp2p#1875)

* core: Add rudimentary benchmark for PeerId::from_bytes and clone

* .github/workflow: Include benchmarks

To ensure changes through pull requests won't make benchmarks fail to
compile or run, run them as part of CI.

* [mdns] Split response packets if necessary. (libp2p#1877)

* [mdns] Split response packets.

Prevent MDNS response packets becoming too large by creating
multi-packet responses. Also skip addresses that don't fit
into a TXT record or contain invalid characters.

* Update protocols/mdns/src/dns.rs

Co-authored-by: Max Inden <mail@max-inden.de>

* Refactor response packet construction.

* Update mdns changelog.

Co-authored-by: Max Inden <mail@max-inden.de>

* core/benches: Add PeerId sort_vec benchmark (libp2p#1878)

* Prepare v0.32 (libp2p#1879)

* [websocket] Update minimum async-tls patch version. (libp2p#1881)

* Update minimum async-tls patch version.

After the upgrade to rustls 0.19, this is the minimum
version required to build.

* Prepare libp2p patch.

* Update async-tls requirement from 0.10.2 to 0.11.0 (libp2p#1884)

* Update async-tls requirement from 0.10.2 to 0.11.0

Updates the requirements on [async-tls](https://github.com/async-std/async-tls) to permit the latest version.
- [Release notes](https://github.com/async-std/async-tls/releases)
- [Commits](async-rs/async-tls@v0.10.2...v0.11.0)

Signed-off-by: dependabot[bot] <support@github.com>

* *: Prepare release

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Max Inden <mail@max-inden.de>

* rename generic types + add default types + update documentation links

* fix broken intra links

* fix tests

* type annotation in example

* fix doc example

* Add compression to gossipsub

* Add snappy compression to the smoke tests

* Stack allocated PeerId (libp2p#1874)

* Stack allocate PeerId.

* Update stuff.

* Upgrade rusttls to fix build.

* Remove unnecessary manual implementations.

* Remove PeerId::into_bytes.

* Remove bytes dependency.

* Perform some cleanup.

* Use Into<kbucket::Key<K>>.

* Update versions and changelogs.

* Fix PR link.

* Fix benchmarks.

Co-authored-by: Roman S. Borschel <roman@parity.io>

* Remove copy and adjust validation ordering

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Roman S. Borschel <roman@parity.io>
Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
Co-authored-by: Max Inden <mail@max-inden.de>
Co-authored-by: blacktemplar <blacktemplar@a1.net>
Co-authored-by: David Craven <david@craven.ch>
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.

None yet

2 participants