use std::{marker::PhantomData, ops::Deref};
use axum_core::{RequestPartsExt, extract::FromRequestParts, response::IntoResponse};
#[cfg(feature = "bb8")]
use bb8_postgres::tokio_postgres::Transaction;
#[cfg(feature = "deadpool")]
use deadpool_postgres::tokio_postgres::Transaction;
use http::{Method, request::Parts};
use parking_lot::{ArcMutexGuard, RawMutex};
use super::extension::{Extension, LazyTx};
pub struct Tx<E = super::Error> {
tx: ArcMutexGuard<RawMutex, LazyTx>,
_error: PhantomData<E>,
}
impl<E> AsRef<Transaction<'static>> for Tx<E> {
fn as_ref(&self) -> &Transaction<'static> {
self.tx.as_ref()
}
}
impl<E> Deref for Tx<E> {
type Target = Transaction<'static>;
fn deref(&self) -> &Self::Target {
self.tx.deref()
}
}
impl<S, E> FromRequestParts<S> for Tx<E>
where
S: Sync,
E: From<super::Error> + IntoResponse,
{
type Rejection = E;
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
let Ok(method) = parts.extract::<Method>().await;
let ext: &Extension = parts
.extensions
.get()
.ok_or(super::Error::MissingExtension)?;
let tx = ext
.get(method == Method::GET || method == Method::HEAD || method == Method::OPTIONS)
.await?;
Ok(Self {
tx,
_error: PhantomData,
})
}
}