Skip to content

Commit 5f37701

Browse files
committed
add chat example
1 parent 4bc7af4 commit 5f37701

File tree

1 file changed

+95
-2
lines changed

1 file changed

+95
-2
lines changed

examples/chat.rs

+95-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,97 @@
1+
//! Cli chat using redis example.
2+
//!
3+
//! A minimal chat example using redis. A user connects to the redis instance
4+
//! and subscribes, and publishes messages across a channel
5+
//!
6+
//! You can test this out by running:
7+
//!
8+
//! cargo run --bin server
9+
//!
10+
//! Then in as many other terminals as you want, run:
11+
//!
12+
//! cargo run --example sub
13+
//!
14+
//! And then in another terminal run:
15+
//!
16+
//! cargo run --example pub
17+
18+
#![warn(rust_2018_idioms)]
19+
20+
use mini_redis::client::{self, Client};
21+
use mini_redis::Result;
22+
use tokio::io::{self, AsyncBufReadExt, AsyncWriteExt, BufReader, Stdin};
23+
124
#[tokio::main]
2-
async fn main() {
3-
unimplemented!();
25+
pub async fn main() -> Result<()> {
26+
// Start by reading the username to then use as the messages author
27+
// when publishing them
28+
let mut stdout = io::stdout();
29+
let mut stdin = BufReader::new(io::stdin());
30+
let mut username = String::new();
31+
stdout.write_all(b"What is your username: ").await?;
32+
stdout.flush().await?;
33+
stdin
34+
.read_line(&mut username)
35+
.await
36+
.map_err(|err| format!("invalid username, {}", err))?;
37+
// Trim /n from input
38+
username = username.trim().to_string();
39+
40+
// Open connections to the mini-redis address.
41+
let addr = "127.0.0.1:6379";
42+
let mut client = client::connect(addr).await?;
43+
44+
// we need a dedicated connection for the subscriber, as `subscribe` consumes the Client.
45+
// We subscribe the chat channel, it's also the channel where client will publish
46+
// messages read from user input
47+
let mut subscriber = client::connect(addr)
48+
.await?
49+
.subscribe(vec!["chat".into()])
50+
.await?;
51+
52+
// Loop receiving new messages on subcriber
53+
let usernamec = username.clone();
54+
tokio::spawn(async move {
55+
loop {
56+
match subscriber.next_message().await {
57+
Ok(Some(message)) => {
58+
let content = String::from_utf8_lossy(&message.content);
59+
// If message comes from own client discard it
60+
// as it's already printed on the screen
61+
if !content.starts_with(&usernamec) {
62+
println!("{}", content);
63+
}
64+
},
65+
Err(err) => {
66+
println!("error: {}", err);
67+
break;
68+
},
69+
Ok(None) => {
70+
println!("server disconnected");
71+
break;
72+
}
73+
}
74+
}
75+
});
76+
77+
loop {
78+
if let Err(err) = read_send_message(&username, &mut stdin, &mut client).await {
79+
println!("error: {}", err);
80+
}
81+
}
82+
}
83+
84+
// Read input from user and publish it as `username: message`
85+
// on the redis server instance
86+
async fn read_send_message(
87+
username: &str,
88+
stdin: &mut BufReader<Stdin>,
89+
client: &mut Client,
90+
) -> Result<()> {
91+
let mut input = String::new();
92+
stdin.read_line(&mut input).await?;
93+
client
94+
.publish("chat", format!("{}: {}", username, input.trim()).into())
95+
.await?;
96+
Ok(())
497
}

0 commit comments

Comments
 (0)