Request/Reply pattern best practice
ufoscout opened this issue · 2 comments
ufoscout commented
Hi, what is the best way to get a reply from a message sent to a channel?
The only way I found to achive it is by creating a second temporary channel for each call and push the response into it.
For example:
pub struct ReplyRequest {
pub message: String,
pub responder: async_channel::Sender<String>,
}
async fn send_a_message(request_tx: async_channel::Sender<ReplyRequest>) {
let (reply_tx, reply_rx) = async_channel::bounded(1);
let message = "Hello world".to_owned();
request_tx.send(ReplyRequest { message, responder: reply_tx }).await.unwrap();
let received_response = reply_rx.recv().await.unwrap();
println!("Replied: {}", received_response);
}
main(){
let (request_tx, request_rx) = async_channel::bounded(1);
your_executor::spawn(async move {
loop {
match request_rx.recv().await {
Ok(message) => {
println!("Received: {}", message.message);
message.responder.send("A new World!".to_owned()).await.unwrap();
}
Err(err) => panic!()
}
}
})
send_a_message(request_tx.clone()).await;
}
Is this the correct way of achieving it?
fogti commented
I have used async-oneshot
for the response in the past. Example code (using macros) https://github.com/YZITE/yxd-auth/blob/3d6acb1371521b8a41874dbae727a9dc133fcb7f/crates/kdc/src/db_.rs#L8-L34
taiki-e commented
I think oneshot is a reasonable pattern here; the performance should not be that different compared to a dedicated oneshot channel because concurrent-queue optimize the single-capacity case