Backpressure and the ConnectionHandler interface
              
              #4585
            
            Replies: 2 comments 3 replies
-
| 
         I'm wondering if  Because if it does then it may not cover one of the use cases where action might be initiated, but later cancelled. For example there could be two ways to retrieve something racing with each other and whichever succeeds first should result in the other one being aborted/cancelled.  | 
  
Beta Was this translation helpful? Give feedback.
-
| 
         I think this is an improvement worth exploring. Though instead of designing a generic mechanism right away, I suggest solving #4667 or #3710 first, and from there try to find a generic mechanism.  | 
  
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
We have a tracking issue around backpressure in
rust-libp2p: #3078. Recently, a discussion came up where lack of backpressure actually causes nodes to crash because they run out of memory: #4572. In this particular case, we'd need backpressure from theBehaviourto theConnectionHandlers.If we were to adapt this interface, we'd have to add several new functions to
NetworkBehaviourandConnectionHandler. Something likeNetworkBehaviour::poll_next_messageto send a new message to aConnectionHandlerand we'd need apoll_ready-like function onConnectionHandlerwhere it can reports its current state.In light of #2863, I would like to suggest a somewhat radical idea of how we could easily fix this:
NetworkBehaviourandConnectionHandlerand with it, theConnectionHandler::{To,From}Behaviourassociated typesmpmc::Channels(naming subject to bike-shedding)If a protocol needs to communicate between
NetworkBehaviourandConnectionHandler, theNetworkBehaviourwould own an instance ofmpmc::Channels. When constructing a newConnectionHandler, the behaviour registers a new key withinmpmc::Channelsfor the new connection.mpmc::Channelswould internally retain a mapping of keys => channelsmpmc::Channels::pollreads messages from all connected channels and "tags" them with the corresponding key (in our case,ConnectionId)mpmc::Channelswould offer several functions for sending messages:poll_all_ready(&mut self, cx: &mut Context): Checks if all connected channels are ready to receive an item.send_to_all(&mut self, msg: M) where M: Clone -> Result<()>: Sends a message into all channels. Fails if any channel is not ready. Should be paired withpoll_all_ready.poll_ready(&mut self, key: K, cx: &mut Context)send_to(&mut self, key: K, msg: M) -> Result<()>Channelwhich implementsSink + Stream. TheNetworkBehaviourhands that to theConnectionHandler.I see several advantages of this scheme:
NetworkBehaviourandConnectionHandlerwithout extending any APIs.ConnectionHandlerinterface becomes simpler because the associated types go away.libp2p-swarmwill be simpler because I think it should be possible to implement the above in a standalone crate.ToSwarmandConnetionHandlerEventwill become simpler.mpmc::Channelsthat support advanced usecases like:The only downside is that users have to add a struct to their custom behaviours and manually poll something within the provided poll functions. However, I'd consider that to be pretty simple scaffholding that is easy to apply once understood. We already expect users to understand
poll-like interfaces when they implement a customNetworkBehaviourso I'd say this is fine.@libp2p/rust-libp2p-maintainers Please voice your opinions.
Beta Was this translation helpful? Give feedback.
All reactions