Stream::merge for arbitrary number of Streams?
- Dominant language
- Rust
- Stars
- 4.1k
- Forks
- 339
- PR merge metrics
- No merged PRs in 30d
Description
Hey! A while ago I was trying out `async-std` to see if I could write a nice abstraction around a thing that I had implemented in C++ in the past and found super painful: listening on multiple network addresses and handling connections from any of them. This is usually to handle IPv4+IPv6, but listening on a specific set of available IP addresses or listening on multiple ports are not uncommon things either. I love how nice the [`TcpListener::incoming`](https://docs.rs/async-std/1.4.0/async_std/net/struct.TcpListener.html#method.incoming) API works in practice so I was trying to build something that felt the same but accepted multiple addresses. I got something working after a while but I struggled for a bit and figured I'd open an issue here to see if there's a place for an API that would make this easier. [Here's the implementation I ended up with](https://github.com/luser/async-server-test/blob/da51eccc08139014e605e8ecdb54bacd3176a7bb/src/main.rs#L14). It uses an `mpsc::unbounded` under the hood, spawns a task for each individual `TcpListener` and has them send their streams of `Result` over the channel for the caller to handle.
This certainly works, but I can't help but wonder if it could be nicer if we had an API like `Stream::merge` that supported an arbitrary number of `Stream`s. Something like `stream::from_iter(...).flatten()` but yielding the first available item from any stream would make this fairly trivial to write, something like:
```rust
async fn accept_on_addrs(addrs: impl ToSocketAddrs) -> Result> {
let addrs = addrs.to_socket_addrs().await?;
Ok(stream::merge_from(stream::from_iter(addrs)
.then(|addr| async move {
let listener = TcpListener::bind(addr).await?;
listener.incoming()
})))
}
```
Contributor guide
Research direction
Start by reading the existing Stream and TcpListener::incoming APIs, then compare the linked async-server-test implementation and its mpsc::unbounded approach. Determine where an arbitrary-stream merge API would fit and define completion around supporting the multi-listener use case described in the issue without requiring each caller to build its own channel and tasks.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- networking
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100