async-rs / async-rs/async-std

Async chat server example connection_writer_loop() might not be necessary

Open
#1,068 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
4.1k
Forks
339
PR merge metrics
No merged PRs in 30d

Description

# Documentation
Async chat server example is using `connection_writer_loop()` task to ensure, that client messages will not be interleaved. https://book.async.rs/tutorial/sending_messages

What if `broker_loop()` will send client messages back to `connection_loop()` instead of creating `connection_writer_loop()` and passing `Acr` all around? This can IMO lead to cleaner design, what is always good in tutorial. Also `Acr` is not necessary then, because TcpStream never escapes `connection_loop()`. We can also use `let (socket_reader, mut socket_writer) = (&stream, &stream);` pattern here.

We can then write something like this:
```rust
async fn connection_loop(client_id: i32, broker: Sender, stream: TcpStream) -> Result<()> {
let (socket_reader, mut socket_writer) = (&stream, &stream);

let reader = BufReader::new(socket_reader);
let mut lines = reader.lines();

let name = match lines.next().await {
None => Err("peer disconnected immediately")?,
Some(line) => line?,
};
broker.send(Event::NewPeer { name: name.clone(), stream: Arc::clone(&stream) }).await // 3
.unwrap();

let (peer_sender, peer_receiver) = channel::unbounded::();
broker
.send(ClientEvent::NewPeer {
client_id,
sender: peer_sender,
})
.await
.unwrap();

loop {
select! {
line = lines.next().fuse() => {
let line = line?;
let (dest, msg) = match line.find(':') {
None => continue,
Some(idx) => (&line[..idx], line[idx + 1 ..].trim()),
};
let dest: Vec = dest.split(',').map(|name| name.trim().to_string()).collect();
let msg: String = msg.to_string();

broker.send(Event::Message { // 4
from: name.clone(),
to: dest,
msg,
}).await.unwrap();
},
message = peer_receiver.next().fuse() => match message {
None => {
break;
}
Some(message) => {
socket_writer.send(msg.as_bytes()).await?;
}
}
}
}
broker.send(ClientEvent::PeerGone { client_id }).await.unwrap();

Ok(())
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.