use crate::ActixRoute;
use actix_web::dev::ServerHandle;
use actix_web::{App, HttpServer};
use alux_http::{HttpServerAlg, HttpServerSetup};
use tokio::task::JoinHandle;
type ActixServerError = Box<dyn std::error::Error + Send + Sync>;
const DRAIN: u64 = 5;
#[derive(Debug, Default)]
pub struct ActixServer;
pub struct ActixOpen {
handle: ServerHandle,
task: JoinHandle<Result<(), ActixServerError>>,
}
impl Drop for ActixOpen {
fn drop(&mut self) {
let stopping = self.handle.stop(true);
drop(stopping);
self.task.abort();
}
}
impl HttpServerAlg for ActixServer {
type Program = ActixRoute;
type Open = ActixOpen;
type Error = ActixServerError;
async fn open(&mut self, setup: HttpServerSetup<Self::Program>) -> Result<Self::Open, Self::Error> {
let (bind, route) = setup.into_parts();
let configure = route.into_actix();
let listener = std::net::TcpListener::bind(bind.address())?;
let server = HttpServer::new(move || App::new().configure(configure.clone()))
.shutdown_timeout(DRAIN)
.disable_signals()
.listen(listener)?
.run();
let handle = server.handle();
let task = actix_web::rt::spawn(async move { server.await.map_err(Into::into) });
Ok(ActixOpen { handle, task })
}
async fn close(&mut self, open: &mut Self::Open) -> Result<(), Self::Error> {
open.handle.stop(true).await;
if !open.task.is_finished() {
let _ = (&mut open.task).await;
}
Ok(())
}
async fn end(&mut self, open: &mut Self::Open) -> Result<(), Self::Error> {
self.close(open).await
}
}