use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
use sqlx::PgPool;
use tower::{Layer, Service};
use crate::orm::postgres::pool;
#[derive(Clone)]
pub struct OrmLayer {
pool: PgPool,
}
impl OrmLayer {
pub fn new(pool: PgPool) -> Self {
crate::orm::n1::auto_configure();
Self { pool }
}
}
impl<S> Layer<S> for OrmLayer {
type Service = OrmService<S>;
fn layer(&self, inner: S) -> Self::Service {
OrmService {
inner,
pool: self.pool.clone(),
}
}
}
#[derive(Clone)]
pub struct OrmService<S> {
inner: S,
pool: PgPool,
}
impl<S, ReqBody> Service<axum::http::Request<ReqBody>> for OrmService<S>
where
S: Service<axum::http::Request<ReqBody>> + Send + 'static,
S::Future: Send + 'static,
ReqBody: Send + 'static,
{
type Response = S::Response;
type Error = S::Error;
type Future = Pin<Box<dyn Future<Output = Result<S::Response, S::Error>> + Send + 'static>>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, req: axum::http::Request<ReqBody>) -> Self::Future {
crate::orm::n1::reset();
let pool = self.pool.clone();
let future = self.inner.call(req);
Box::pin(pool::scope_pool(pool, future))
}
}