Add a back-pressure-friendly alternative to NetworkService::write_notifications 🎉 (#6692)

* Add NetworkService::send_notifications

* Doc

* Doc

* API adjustment

* Address concerns

* Make it compile

* Start implementation

* Progress in the implementation

* Change implementation strategy again

* More work before weekend

* Finish changes

* Minor doc fix

* Revert some minor changes

* Apply suggestions from code review

* GroupError -> NotifsHandlerError

* Apply suggestions from code review

Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>

* state_transition_waker -> close_waker

* Apply suggestions from code review

Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>

* Finish renames in service.rs

* More renames

* More review suggestsions applied

* More review addressing

* Final change

* 512 -> 2048

Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
This commit is contained in:
Pierre Krieger
2020-07-29 13:23:19 +02:00
committed by GitHub
parent e674d64a72
commit 1ab7719314
12 changed files with 955 additions and 431 deletions
+73 -24
View File
@@ -17,10 +17,11 @@
use crate::{
config::{ProtocolId, Role}, block_requests, light_client_handler, finality_requests,
peer_info, discovery::{DiscoveryBehaviour, DiscoveryConfig, DiscoveryOut},
protocol::{message::{self, Roles}, CustomMessageOutcome, Protocol},
Event, ObservedRole, DhtEvent, ExHashT,
protocol::{message::{self, Roles}, CustomMessageOutcome, NotificationsSink, Protocol},
ObservedRole, DhtEvent, ExHashT,
};
use bytes::Bytes;
use codec::Encode as _;
use libp2p::NetworkBehaviour;
use libp2p::core::{Multiaddr, PeerId, PublicKey};
@@ -98,11 +99,53 @@ pub enum BehaviourOut<B: BlockT> {
request_duration: Duration,
},
/// Any event represented by the [`Event`] enum.
/// Opened a substream with the given node with the given notifications protocol.
///
/// > **Note**: The [`Event`] enum contains the events that are available through the public
/// > API of the library.
Event(Event),
/// The protocol is always one of the notification protocols that have been registered.
NotificationStreamOpened {
/// Node we opened the substream with.
remote: PeerId,
/// The concerned protocol. Each protocol uses a different substream.
engine_id: ConsensusEngineId,
/// Object that permits sending notifications to the peer.
notifications_sink: NotificationsSink,
/// Role of the remote.
role: ObservedRole,
},
/// The [`NotificationsSink`] object used to send notifications with the given peer must be
/// replaced with a new one.
///
/// This event is typically emitted when a transport-level connection is closed and we fall
/// back to a secondary connection.
NotificationStreamReplaced {
/// Id of the peer we are connected to.
remote: PeerId,
/// The concerned protocol. Each protocol uses a different substream.
engine_id: ConsensusEngineId,
/// Replacement for the previous [`NotificationsSink`].
notifications_sink: NotificationsSink,
},
/// Closed a substream with the given node. Always matches a corresponding previous
/// `NotificationStreamOpened` message.
NotificationStreamClosed {
/// Node we closed the substream with.
remote: PeerId,
/// The concerned protocol. Each protocol uses a different substream.
engine_id: ConsensusEngineId,
},
/// Received one or more messages from the given node using the given protocol.
NotificationsReceived {
/// Node we received the message from.
remote: PeerId,
/// Concerned protocol and associated message.
messages: Vec<(ConsensusEngineId, Bytes)>,
},
/// Event generated by a DHT.
Dht(DhtEvent),
}
impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
@@ -165,8 +208,6 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
/// Registers a new notifications protocol.
///
/// After that, you can call `write_notifications`.
///
/// Please call `event_stream` before registering a protocol, otherwise you may miss events
/// about the protocol that you have registered.
///
@@ -182,14 +223,14 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
let handshake_message = Roles::from(&self.role).encode();
let list = self.substrate.register_notifications_protocol(engine_id, protocol_name, handshake_message);
for (remote, roles) in list {
for (remote, roles, notifications_sink) in list {
let role = reported_roles_to_observed_role(&self.role, remote, roles);
let ev = Event::NotificationStreamOpened {
self.events.push_back(BehaviourOut::NotificationStreamOpened {
remote: remote.clone(),
engine_id,
role,
};
self.events.push_back(BehaviourOut::Event(ev));
notifications_sink: notifications_sink.clone(),
});
}
}
@@ -278,26 +319,34 @@ Behaviour<B, H> {
CustomMessageOutcome::FinalityProofRequest { target, block_hash, request } => {
self.finality_proof_requests.send_request(&target, block_hash, request);
},
CustomMessageOutcome::NotificationStreamOpened { remote, protocols, roles } => {
CustomMessageOutcome::NotificationStreamOpened { remote, protocols, roles, notifications_sink } => {
let role = reported_roles_to_observed_role(&self.role, &remote, roles);
for engine_id in protocols {
self.events.push_back(BehaviourOut::Event(Event::NotificationStreamOpened {
self.events.push_back(BehaviourOut::NotificationStreamOpened {
remote: remote.clone(),
engine_id,
role: role.clone(),
}));
notifications_sink: notifications_sink.clone(),
});
}
},
CustomMessageOutcome::NotificationStreamClosed { remote, protocols } =>
CustomMessageOutcome::NotificationStreamReplaced { remote, protocols, notifications_sink } =>
for engine_id in protocols {
self.events.push_back(BehaviourOut::Event(Event::NotificationStreamClosed {
self.events.push_back(BehaviourOut::NotificationStreamReplaced {
remote: remote.clone(),
engine_id,
}));
notifications_sink: notifications_sink.clone(),
});
},
CustomMessageOutcome::NotificationStreamClosed { remote, protocols } =>
for engine_id in protocols {
self.events.push_back(BehaviourOut::NotificationStreamClosed {
remote: remote.clone(),
engine_id,
});
},
CustomMessageOutcome::NotificationsReceived { remote, messages } => {
let ev = Event::NotificationsReceived { remote, messages };
self.events.push_back(BehaviourOut::Event(ev));
self.events.push_back(BehaviourOut::NotificationsReceived { remote, messages });
},
CustomMessageOutcome::PeerNewBest(peer_id, number) => {
self.light_client_handler.update_best_block(&peer_id, number);
@@ -393,16 +442,16 @@ impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<DiscoveryOut>
self.substrate.add_discovered_nodes(iter::once(peer_id));
}
DiscoveryOut::ValueFound(results) => {
self.events.push_back(BehaviourOut::Event(Event::Dht(DhtEvent::ValueFound(results))));
self.events.push_back(BehaviourOut::Dht(DhtEvent::ValueFound(results)));
}
DiscoveryOut::ValueNotFound(key) => {
self.events.push_back(BehaviourOut::Event(Event::Dht(DhtEvent::ValueNotFound(key))));
self.events.push_back(BehaviourOut::Dht(DhtEvent::ValueNotFound(key)));
}
DiscoveryOut::ValuePut(key) => {
self.events.push_back(BehaviourOut::Event(Event::Dht(DhtEvent::ValuePut(key))));
self.events.push_back(BehaviourOut::Dht(DhtEvent::ValuePut(key)));
}
DiscoveryOut::ValuePutFailed(key) => {
self.events.push_back(BehaviourOut::Event(Event::Dht(DhtEvent::ValuePutFailed(key))));
self.events.push_back(BehaviourOut::Dht(DhtEvent::ValuePutFailed(key)));
}
DiscoveryOut::RandomKademliaStarted(protocols) => {
for protocol in protocols {