seanmonstar / warp

A super-easy, composable, web server framework for warp speeds.
https://seanmonstar.com/post/176530511587/warp
MIT License
9.61k stars 724 forks source link

Possibility to use !Send futures in warp #528

Open ancwrd1 opened 4 years ago

ancwrd1 commented 4 years ago

I have an application which is based internally on Actix actor framework. I would like to refactor it to use warp instead of actix-web, however the issue is the futures incompatibility, because warp expects Send futures and actix uses !Send futures for it's actors.

So the question is whether it is practically doable?

Code example:


async fn status() -> Result<impl warp::Reply, Infallible> {
    let res = RemotingServiceActor::from_registry().send(IsOnlineMsg).await;

    let online = if let Ok(true) = res { "online" } else { "offline" };

    let reply = warp::reply::with_status(online, warp::http::StatusCode::OK);

    Ok(warp::reply::with_header(reply, "Context-Type", "text/html"))
}

...

let status_path = warp::path!("status").and(warp::get()).and_then(status);
commons::spawn(warp::serve(status_path).run(([127, 0, 0, 1], 7311)));

Compilation fails with:

508 |         let status_path = warp::path!("status").and(warp::get()).and_then(status);
    |                                                                  ^^^^^^^^ future returned by `status` is not `Send`
    |
    = help: within `impl core::future::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::RefCell<std::collections::HashMap<std::string::String, futures_channel::oneshot::Sender<domain::proto::remoting::R_RemoteDelivery>>>>`
note: future is not `Send` as this value is used across an await

181 |     let res = RemotingServiceActor::from_registry().send(IsOnlineMsg).await;
    |               -------------------------------------------------------^^^^^^- `RemotingServiceActor::from_registry().send(IsOnlineMsg)` is later dropped here
    |               |
    |               await occurs here, with `RemotingServiceActor::from_registry().send(IsOnlineMsg)` maybe used later
    |               has type `actix::address::message::Request<services::remoting::RemotingService, message::IsOnlineMsg>`

error: future cannot be sent between threads safely
seanmonstar commented 4 years ago

It might be possible to loosen the Send requirements in some places, but probably not quickly.