Incömplete
Incömplete

Reputation: 943

How to pass a std::sync::mpsc::Sender<T> to a handler in warp?

In warp (rust), how can I pass a std::sync::mpsc::Sender<T> to my business handlers? The following codes complains that std::sync::mpsc::Sender<T> is not Sync.

I understand that I possibly could wrap my_sender with something like Arc<RwLock<Sender<T>>>, but that doesn't seem right, since the purpose of channel is to enable inter-threads communication.

Do I have to wrap the Sender<T>, or there is a better way to do this?

use std;
use warp::{self, Filter};

fn with_sender<T: Send + Sync>(
    sender: std::sync::mpsc::Sender<T>,
) -> impl Filter<Extract = (std::sync::mpsc::Sender<T>,), Error = std::convert::Infallible> + Clone
{
    warp::any().map(move || sender.clone())
}

// later in main():
let (my_sender, my_receiver) = std::sync::mpsc::channel::<MySyncAndSendType>();

let routes = (warp::get()
    .and(warp::path!("some" / "path"))
    .map(my_handlers::handler_1)
    .map(turn_result_to_json)
    .or(warp::post()
        .and(warp::path!("some" / "other" / "path"))
        .and(warp::multipart::form().max_length(10 * 1024 * 1024))
        .and(with_sender(my_sender.clone()))
        // -------------------------------------------------------------------------
        // -------> I need my_sender in the function my_handlers::handler_2 <-------
        .and_then(|form, my_sender| async move {
            Ok::<_, Infallible>(my_handlers::handler_2(form, my_sender).await)
        })
        .map(turn_result_to_json)));

warp::serve(routes).run(([127, 0, 0, 1], 1234)).await;

Upvotes: 1

Views: 1041

Answers (1)

Peter Hall
Peter Hall

Reputation: 58805

Sender is not Sync, so it cannot be shared, but it is Send, so you can move it into the async task.

The problem with your code is that the closure is capturing its environment by reference, even though the async block inside is move. You should just need to make the closure move too:

.and_then(move |form, my_sender| async move {
    Ok::<_, Infallible>(my_handlers::handler_2(form, my_sender).await)
})

Upvotes: 1

Related Questions