use std::{ops::Deref, pin::Pin, sync::Arc};
use anyhow::Error;
use futures::{Future, FutureExt};
use http::{Request, Response};
use crate::runners::wcgi;
use super::DcgiInstanceFactory;
use super::super::Body;
#[derive(Clone, Debug)]
pub(crate) struct Handler {
state: Arc<SharedState>,
inner: wcgi::Handler,
}
impl Handler {
pub(crate) fn new(handler: wcgi::Handler) -> Self {
Handler {
state: Arc::new(SharedState {
inner: handler.deref().clone(),
factory: DcgiInstanceFactory::new(),
master_lock: Default::default(),
}),
inner: handler,
}
}
#[tracing::instrument(level = "debug", skip_all, err)]
pub(crate) async fn handle(
&self,
req: Request<hyper::body::Incoming>,
) -> Result<Response<Body>, Error> {
let guard_token = self.state.master_lock.clone().lock_owned().await;
self.inner.handle(req, guard_token).await
}
}
impl Deref for Handler {
type Target = Arc<SharedState>;
fn deref(&self) -> &Self::Target {
&self.state
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub(crate) struct SharedState {
#[allow(dead_code)]
pub(crate) inner: Arc<wcgi::SharedState>,
factory: DcgiInstanceFactory,
master_lock: Arc<tokio::sync::Mutex<()>>,
}
impl tower::Service<Request<hyper::body::Incoming>> for Handler {
type Response = Response<Body>;
type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<Response<Body>, Error>> + Send>>;
fn poll_ready(
&mut self,
_cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), Self::Error>> {
std::task::Poll::Ready(Ok(()))
}
fn call(&mut self, request: Request<hyper::body::Incoming>) -> Self::Future {
let handler = self.clone();
let fut = async move { handler.handle(request).await };
fut.boxed()
}
}