Actix-web: Utliity function: Starting in a standalone thread.

Created on 18 Dec 2018  路  2Comments  路  Source: actix/actix-web

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>

Most helpful comment

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());
    }
}

All 2 comments

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());
    }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

kocoten1992 picture kocoten1992  路  3Comments

naturallymitchell picture naturallymitchell  路  4Comments

mcelkys picture mcelkys  路  4Comments

icommit picture icommit  路  3Comments

bbigras picture bbigras  路  5Comments