I have a program that that uses native threads already, and I would like to embed actix_web App in it, to serve HTTP requests.
The problem is - it's hard to construct App while passing all the possible failures (eg. bind failing, and control (Addr<Server>) back from the thread where App has to be constructed (because actix is all !Sync).
Ideally, there would be a nicer way to do it, that would return a ActixThread handle that would gracefully shut-down App on its drop, and also allow sending messages to the App from the outside, and possibly other things.
Something like App::start_as_thread<E>(constr_f: FnOnce()-> Result<actix_web::App, E>) -> Result<ActixAppThread, E>
I've baked something myself, for my own needs. For reference, in case anyone ever gets here from google search.
//! Bunch of utility functions for handling actix
use crate::prelude::*;
use futures::Future;
pub struct ActixAppThread {
pub join: Option<std::thread::JoinHandle<Result<()>>>,
pub actix_addr: actix_web::actix::Addr<actix_net::server::Server>,
}
/// https://github.com/actix/actix-web/issues/638
pub fn construct_actix_thread<E, H, F>(
f: impl FnOnce() -> std::result::Result<actix_web::server::HttpServer<H, F>, E> + Send + 'static,
) -> std::result::Result<ActixAppThread, E>
where
E: std::error::Error + Send + Sync + 'static,
H: actix_web::server::IntoHttpHandler + 'static,
F: Fn() -> H + Send + Clone + 'static,
{
let (tx, rx) = std::sync::mpsc::channel();
let join = std::thread::spawn(move || {
let sys = actix::System::new("embedded-http-server");
match f() {
Ok(app) => {
tx.send(Ok(app.system_exit().start()))?;
sys.run();
}
Err(e) => {
tx.send(Err(e))?;
}
}
Ok(())
});
let addr = rx.recv().unwrap()?;
Ok(ActixAppThread {
join: Some(join),
actix_addr: addr,
})
}
impl ActixAppThread {
fn stop(&self) {
self.actix_addr
.send(actix_web::server::StopServer { graceful: true })
.wait()
.unwrap()
.unwrap();
}
}
impl Drop for ActixAppThread {
fn drop(&mut self) {
self.stop();
self.join.take().map(|j| j.join().unwrap());
}
}
Most helpful comment
I've baked something myself, for my own needs. For reference, in case anyone ever gets here from google search.