Replaced async_trait with async in traits from 2024 edition

This commit is contained in:
Martin Berg Alstad 2025-03-07 22:40:10 +01:00
parent 2f1eb4df3a
commit 5a77407297
Signed by: martials
GPG Key ID: 706F53DD087A91DE
16 changed files with 90 additions and 127 deletions

3
Cargo.lock generated
View File

@ -488,8 +488,6 @@ dependencies = [
name = "diesel-crud-trait" name = "diesel-crud-trait"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async-trait",
"deadpool-diesel",
"diesel", "diesel",
"diesel-async", "diesel-async",
"thiserror 2.0.12", "thiserror 2.0.12",
@ -1072,7 +1070,6 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
name = "lib" name = "lib"
version = "1.5.0" version = "1.5.0"
dependencies = [ dependencies = [
"async-trait",
"axum", "axum",
"chrono", "chrono",
"deadpool-diesel", "deadpool-diesel",

View File

@ -26,7 +26,6 @@ tower = { version = "0.5", optional = true }
tower-http = { version = "0.6", optional = true, features = ["trace", "cors", "normalize-path"] } tower-http = { version = "0.6", optional = true, features = ["trace", "cors", "normalize-path"] }
mime = { version = "0.3", optional = true } mime = { version = "0.3", optional = true }
# Async # Async
async-trait = { workspace = true }
tokio = { workspace = true, optional = true, features = ["fs", "rt-multi-thread"] } tokio = { workspace = true, optional = true, features = ["fs", "rt-multi-thread"] }
tokio-util = { version = "0.7", optional = true, features = ["io"] } tokio-util = { version = "0.7", optional = true, features = ["io"] }
# Database # Database
@ -59,7 +58,6 @@ derive_more = { workspace = true, features = ["from", "constructor"] }
[workspace.dependencies] [workspace.dependencies]
# Async # Async
tokio = "1.40" tokio = "1.40"
async-trait = "0.1"
# Database # Database
diesel = "2.2" diesel = "2.2"
diesel-async = "0.5" diesel-async = "0.5"

View File

@ -9,6 +9,6 @@ pub(crate) struct PrimaryKey {
pub(crate) fn return_type(output: proc_macro2::TokenStream) -> proc_macro2::TokenStream { pub(crate) fn return_type(output: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
quote! { quote! {
std::pin::Pin<Box<dyn core::future::Future<Output = Result<#output, lib::diesel_crud_trait::CrudError>> + Send + 'async_trait>> Result<#output, lib::diesel_crud_trait::CrudError>
} }
} }

View File

@ -1,4 +1,4 @@
use crate::{common, Attributes}; use crate::{Attributes, common};
use quote::quote; use quote::quote;
pub(crate) fn derive_diesel_crud_create_impl( pub(crate) fn derive_diesel_crud_create_impl(
@ -16,37 +16,24 @@ pub(crate) fn derive_diesel_crud_create_impl(
#[automatically_derived] #[automatically_derived]
impl lib::diesel_crud_trait::DieselCrudCreate<#table::table> for #struct_ident { impl lib::diesel_crud_trait::DieselCrudCreate<#table::table> for #struct_ident {
type Insert = #insert; type Insert = #insert;
fn insert<'a, 'async_trait>(insert: Self::Insert, conn: &'a mut diesel_async::AsyncPgConnection) -> #return_type async fn insert(insert: Self::Insert, conn: &mut diesel_async::AsyncPgConnection) -> #return_type {
where use diesel::associations::HasTable;
Self: Sized + Sync + 'a, diesel_async::RunQueryDsl::get_result(
'a: 'async_trait, diesel::dsl::insert_into(#table::table::table()).values(insert),
{ conn
Box::pin(async move { )
use diesel::associations::HasTable; .await
diesel_async::RunQueryDsl::get_result( .map_err(Into::into)
diesel::dsl::insert_into(#table::table::table()).values(insert),
conn
)
.await
.map_err(Into::into)
})
} }
fn insert_many<'a, 'b, 'async_trait>(insert: &'a [Self::Insert], conn: &'b mut diesel_async::AsyncPgConnection) -> #many_return_type async fn insert_many(insert: &[Self::Insert], conn: &mut diesel_async::AsyncPgConnection) -> #many_return_type {
where use diesel::associations::HasTable;
Self: Sized + Sync + 'async_trait, diesel_async::RunQueryDsl::get_results(
'a: 'async_trait, diesel::dsl::insert_into(#table::table::table()).values(insert),
'b: 'async_trait, conn
{ )
Box::pin(async move { .await
use diesel::associations::HasTable; .map_err(Into::into)
diesel_async::RunQueryDsl::get_results(
diesel::dsl::insert_into(#table::table::table()).values(insert),
conn
)
.await
.map_err(Into::into)
})
} }
} }
} }

View File

@ -1,4 +1,4 @@
use crate::{common, Attributes, PrimaryKey}; use crate::{Attributes, PrimaryKey, common};
use quote::quote; use quote::quote;
pub(crate) fn derive_diesel_crud_delete_impl( pub(crate) fn derive_diesel_crud_delete_impl(
@ -22,24 +22,18 @@ pub(crate) fn derive_diesel_crud_delete_impl(
#[automatically_derived] #[automatically_derived]
impl lib::diesel_crud_trait::DieselCrudDelete for #struct_ident { impl lib::diesel_crud_trait::DieselCrudDelete for #struct_ident {
type PK = #pk_type; type PK = #pk_type;
fn delete<'a, 'async_trait>(pk: Self::PK, conn: &'a mut diesel_async::AsyncPgConnection) -> #return_type async fn delete(pk: Self::PK, conn: &mut diesel_async::AsyncPgConnection) -> #return_type {
where use diesel::QueryDsl;
Self: Sized + Sync + 'a, use diesel::associations::HasTable;
'a: 'async_trait, diesel_async::RunQueryDsl::get_result(
{ diesel::delete(
Box::pin(async move { #table::table
use diesel::QueryDsl; .filter(diesel::expression_methods::ExpressionMethods::eq(#table::#pk_ident, pk))
use diesel::associations::HasTable; ),
diesel_async::RunQueryDsl::get_result( conn,
diesel::delete( )
#table::table .await
.filter(diesel::expression_methods::ExpressionMethods::eq(#table::#pk_ident, pk)) .map_err(Into::into)
),
conn,
)
.await
.map_err(Into::into)
})
} }
} }
} }

View File

@ -1,4 +1,4 @@
use crate::{common, Attributes}; use crate::{Attributes, common};
use quote::quote; use quote::quote;
pub(crate) fn derive_diesel_crud_list_impl( pub(crate) fn derive_diesel_crud_list_impl(
@ -13,15 +13,9 @@ pub(crate) fn derive_diesel_crud_list_impl(
quote! { quote! {
#[automatically_derived] #[automatically_derived]
impl lib::diesel_crud_trait::DieselCrudList for #struct_ident { impl lib::diesel_crud_trait::DieselCrudList for #struct_ident {
fn list<'a, 'async_trait>(conn: &'a mut diesel_async::AsyncPgConnection) -> #return_type async fn list(conn: &mut diesel_async::AsyncPgConnection) -> #return_type {
where use diesel::associations::HasTable;
Self: Sized + Sync + 'a, diesel_async::RunQueryDsl::get_results(#table::table::table(), conn).await.map_err(Into::into)
'a: 'async_trait
{
Box::pin(async move {
use diesel::associations::HasTable;
diesel_async::RunQueryDsl::get_results(#table::table::table(), conn).await.map_err(Into::into)
})
} }
} }
} }

View File

@ -1,5 +1,5 @@
use crate::common::PrimaryKey; use crate::common::PrimaryKey;
use crate::{common, Attributes}; use crate::{Attributes, common};
use quote::quote; use quote::quote;
pub(crate) fn derive_diesel_crud_read_impl( pub(crate) fn derive_diesel_crud_read_impl(
@ -20,20 +20,14 @@ pub(crate) fn derive_diesel_crud_read_impl(
#[automatically_derived] #[automatically_derived]
impl lib::diesel_crud_trait::DieselCrudRead for #struct_ident { impl lib::diesel_crud_trait::DieselCrudRead for #struct_ident {
type PK = #pk_type; type PK = #pk_type;
fn read<'a, 'async_trait>(pk: Self::PK, conn: &'a mut diesel_async::AsyncPgConnection) -> #return_type async fn read(pk: Self::PK, conn: &mut diesel_async::AsyncPgConnection) -> #return_type {
where use diesel::associations::HasTable;
Self: Sized + Sync + 'a, diesel_async::RunQueryDsl::get_result(
'a: 'async_trait diesel::QueryDsl::find(#table::table::table(), pk),
{ conn
Box::pin(async move { )
use diesel::associations::HasTable; .await
diesel_async::RunQueryDsl::get_result( .map_err(Into::into)
diesel::QueryDsl::find(#table::table::table(), pk),
conn
)
.await
.map_err(Into::into)
})
} }
} }
} }

View File

@ -1,4 +1,4 @@
use crate::{common, Attributes}; use crate::{Attributes, common};
use quote::quote; use quote::quote;
pub(crate) fn derive_diesel_crud_update_impl( pub(crate) fn derive_diesel_crud_update_impl(
@ -15,20 +15,14 @@ pub(crate) fn derive_diesel_crud_update_impl(
#[automatically_derived] #[automatically_derived]
impl lib::diesel_crud_trait::DieselCrudUpdate for #struct_ident { impl lib::diesel_crud_trait::DieselCrudUpdate for #struct_ident {
type Update = #update; type Update = #update;
fn update<'a, 'async_trait>(update: Self::Update, conn: &'a mut diesel_async::AsyncPgConnection) -> #return_type async fn update(update: Self::Update, conn: &mut diesel_async::AsyncPgConnection) -> #return_type {
where use diesel::associations::HasTable;
Self: Sized + Sync + 'a, diesel_async::RunQueryDsl::get_result(
'a: 'async_trait, diesel::dsl::update(#table::table::table()).set(update),
{ conn,
Box::pin(async move { )
use diesel::associations::HasTable; .await
diesel_async::RunQueryDsl::get_result( .map_err(Into::into)
diesel::dsl::update(#table::table::table()).set(update),
conn,
)
.await
.map_err(Into::into)
})
} }
} }
} }

View File

@ -7,6 +7,4 @@ rust-version = { workspace = true }
[dependencies] [dependencies]
diesel = { workspace = true, features = ["postgres"] } diesel = { workspace = true, features = ["postgres"] }
diesel-async = { workspace = true, features = ["postgres", "deadpool"] } diesel-async = { workspace = true, features = ["postgres", "deadpool"] }
async-trait = "0.1"
deadpool-diesel = { version = "0.6", features = ["postgres"] }
thiserror = { workspace = true } thiserror = { workspace = true }

View File

@ -1,6 +1,5 @@
mod error; mod error;
use async_trait::async_trait;
use diesel::{AsChangeset, Insertable}; use diesel::{AsChangeset, Insertable};
use diesel_async::AsyncPgConnection; use diesel_async::AsyncPgConnection;
pub use error::CrudError; pub use error::CrudError;
@ -28,17 +27,19 @@ pub trait DieselCrud<Table>:
/// - `conn` - The database connection /// - `conn` - The database connection
/// # Returns /// # Returns
/// A result containing the inserted entity or a `CrudError` /// A result containing the inserted entity or a `CrudError`
#[async_trait]
pub trait DieselCrudCreate<Table> pub trait DieselCrudCreate<Table>
where where
Self: Sized, Self: Sized,
{ {
type Insert: Insertable<Table>; type Insert: Insertable<Table>;
async fn insert(insert: Self::Insert, conn: &mut AsyncPgConnection) -> Result<Self, CrudError>; fn insert(
async fn insert_many( insert: Self::Insert,
conn: &mut AsyncPgConnection,
) -> impl Future<Output = Result<Self, CrudError>>;
fn insert_many(
insert: &[Self::Insert], insert: &[Self::Insert],
conn: &mut AsyncPgConnection, conn: &mut AsyncPgConnection,
) -> Result<Vec<Self>, CrudError>; ) -> impl Future<Output = Result<Vec<Self>, CrudError>>;
} }
/// Gets an entity from the database /// Gets an entity from the database
@ -52,13 +53,15 @@ where
/// # Returns /// # Returns
/// A result containing the entity or a `CrudError`. /// A result containing the entity or a `CrudError`.
/// If the entity is not found, the error should be `CrudError::NotFound`. /// If the entity is not found, the error should be `CrudError::NotFound`.
#[async_trait]
pub trait DieselCrudRead pub trait DieselCrudRead
where where
Self: Sized, Self: Sized,
{ {
type PK; type PK;
async fn read(pk: Self::PK, conn: &mut AsyncPgConnection) -> Result<Self, CrudError>; fn read(
pk: Self::PK,
conn: &mut AsyncPgConnection,
) -> impl Future<Output = Result<Self, CrudError>>;
} }
/// Updates an entity in the database /// Updates an entity in the database
@ -73,13 +76,15 @@ where
/// # Returns /// # Returns
/// A result containing the old entry of the entity if successful or a `CrudError`. /// A result containing the old entry of the entity if successful or a `CrudError`.
/// If the entity is not found, the error should be `CrudError::NotFound`. /// If the entity is not found, the error should be `CrudError::NotFound`.
#[async_trait]
pub trait DieselCrudUpdate pub trait DieselCrudUpdate
where where
Self: Sized, Self: Sized,
{ {
type Update: AsChangeset; type Update: AsChangeset;
async fn update(update: Self::Update, conn: &mut AsyncPgConnection) -> Result<Self, CrudError>; fn update(
update: Self::Update,
conn: &mut AsyncPgConnection,
) -> impl Future<Output = Result<Self, CrudError>>;
} }
/// Deletes an entity from the database /// Deletes an entity from the database
@ -93,13 +98,15 @@ where
/// # Returns /// # Returns
/// A result containing the deleted entity or a `CrudError`. /// A result containing the deleted entity or a `CrudError`.
/// If the entity is not found, the error should be `CrudError::NotFound`. /// If the entity is not found, the error should be `CrudError::NotFound`.
#[async_trait]
pub trait DieselCrudDelete pub trait DieselCrudDelete
where where
Self: Sized, Self: Sized,
{ {
type PK; type PK;
async fn delete(pk: Self::PK, conn: &mut AsyncPgConnection) -> Result<Self, CrudError>; fn delete(
pk: Self::PK,
conn: &mut AsyncPgConnection,
) -> impl Future<Output = Result<Self, CrudError>>;
} }
/// Lists all entities in the table /// Lists all entities in the table
@ -109,10 +116,9 @@ where
/// - `conn` - The database connection /// - `conn` - The database connection
/// # Returns /// # Returns
/// A result containing a Vec of entities or a `CrudError`. /// A result containing a Vec of entities or a `CrudError`.
#[async_trait]
pub trait DieselCrudList pub trait DieselCrudList
where where
Self: Sized, Self: Sized,
{ {
async fn list(conn: &mut AsyncPgConnection) -> Result<Vec<Self>, CrudError>; fn list(conn: &mut AsyncPgConnection) -> impl Future<Output = Result<Vec<Self>, CrudError>>;
} }

View File

@ -1,14 +1,13 @@
use { use {
crate::{serde::response::BaseResponse, serde::traits::DeserializeInto}, crate::{serde::response::BaseResponse, serde::traits::DeserializeInto},
async_trait::async_trait,
axum::{ axum::{
Json,
body::to_bytes, body::to_bytes,
response::{IntoResponse, Response}, response::{IntoResponse, Response},
Json,
}, },
serde::{ serde::{
de::{DeserializeOwned, Error},
Serialize, Serialize,
de::{DeserializeOwned, Error},
}, },
}; };
@ -18,7 +17,6 @@ impl<T: Serialize> IntoResponse for BaseResponse<T> {
} }
} }
#[async_trait]
impl DeserializeInto for Response { impl DeserializeInto for Response {
async fn deserialize_into<T: DeserializeOwned>(self) -> Result<T, serde_json::Error> { async fn deserialize_into<T: DeserializeOwned>(self) -> Result<T, serde_json::Error> {
let body = to_bytes(self.into_body(), usize::MAX).await.map_err(|e| { let body = to_bytes(self.into_body(), usize::MAX).await.map_err(|e| {

View File

@ -13,8 +13,8 @@
/// use lib::router; /// use lib::router;
/// async fn simplify(path: axum::extract::path::Path<String>) {} /// async fn simplify(path: axum::extract::path::Path<String>) {}
/// router!("/simplify", lib::routes!( /// router!("/simplify", lib::routes!(
/// get "/:exp" => simplify, /// get "/{exp}" => simplify,
/// get "/table/:exp" => || async {} /// get "/table/{exp}" => async || {}
/// )); /// ));
/// ``` /// ```
#[macro_export] #[macro_export]
@ -92,8 +92,8 @@ macro_rules! join_routes {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use axum::extract::State;
use axum::Router; use axum::Router;
use axum::extract::State;
async fn index() {} async fn index() {}

View File

@ -1,17 +1,16 @@
use async_trait::async_trait;
use deadpool_diesel::Status; use deadpool_diesel::Status;
use derive_more::From; use derive_more::From;
use diesel_async::AsyncPgConnection; use diesel_async::AsyncPgConnection;
use diesel_async::pooled_connection::deadpool::{Object, PoolError}; use diesel_async::pooled_connection::deadpool::{Object, PoolError};
use lib::diesel::pool::PgPool; use lib::diesel::pool::PgPool;
#[async_trait]
pub trait GetConnection: Clone + Send + Sync { pub trait GetConnection: Clone + Send + Sync {
async fn get(&self) -> Result<Object<AsyncPgConnection>, GetConnectionError>; fn get(
&self,
) -> impl Future<Output = Result<Object<AsyncPgConnection>, GetConnectionError>> + Send;
fn status(&self) -> Status; fn status(&self) -> Status;
} }
#[async_trait]
impl GetConnection for PgPool { impl GetConnection for PgPool {
async fn get(&self) -> Result<Object<AsyncPgConnection>, GetConnectionError> { async fn get(&self) -> Result<Object<AsyncPgConnection>, GetConnectionError> {
self.get().await.map_err(Into::into) self.get().await.map_err(Into::into)

View File

@ -1,7 +1,7 @@
use async_trait::async_trait;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
#[async_trait]
pub trait DeserializeInto { pub trait DeserializeInto {
async fn deserialize_into<T: DeserializeOwned>(self) -> Result<T, serde_json::Error>; fn deserialize_into<T: DeserializeOwned>(
self,
) -> impl Future<Output = Result<T, serde_json::Error>>;
} }

View File

@ -1,7 +1,6 @@
use crate::diesel::DieselError; use crate::diesel::DieselError;
use crate::diesel::get_connection::{GetConnection, GetConnectionError}; use crate::diesel::get_connection::{GetConnection, GetConnectionError};
use crate::diesel::pool::PgPool; use crate::diesel::pool::PgPool;
use async_trait::async_trait;
use deadpool_diesel::Status; use deadpool_diesel::Status;
use deadpool_diesel::postgres::BuildError; use deadpool_diesel::postgres::BuildError;
use derive_more::From; use derive_more::From;
@ -32,7 +31,6 @@ pub async fn create_test_pool_url_with_size(
Ok(PoolStub(pool)) Ok(PoolStub(pool))
} }
#[async_trait]
impl GetConnection for PoolStub { impl GetConnection for PoolStub {
async fn get(&self) -> Result<Object<AsyncPgConnection>, GetConnectionError> { async fn get(&self) -> Result<Object<AsyncPgConnection>, GetConnectionError> {
let mut conn = self.0.get().await?; let mut conn = self.0.get().await?;

View File

@ -6,6 +6,7 @@ use lib::diesel::DieselError;
use testcontainers_modules::postgres::Postgres; use testcontainers_modules::postgres::Postgres;
use testcontainers_modules::testcontainers::runners::AsyncRunner; use testcontainers_modules::testcontainers::runners::AsyncRunner;
use testcontainers_modules::testcontainers::{ContainerAsync, TestcontainersError}; use testcontainers_modules::testcontainers::{ContainerAsync, TestcontainersError};
use tokio::task::JoinError;
/// When the TestContainer is dropped, the container will be removed. /// When the TestContainer is dropped, the container will be removed.
/// # Errors /// # Errors
@ -16,11 +17,15 @@ pub struct TestContainer {
pub pool: PgPool, pub pool: PgPool,
} }
const TEST_CONTAINERS_INTERNAL_PORT: u16 = 5432;
pub async fn create_test_containers_pool() -> Result<TestContainer, ContainerError> { pub async fn create_test_containers_pool() -> Result<TestContainer, ContainerError> {
let container = create_postgres_container().await?; let container = create_postgres_container().await?;
let connection_string = format!( let connection_string = format!(
"postgres://postgres:postgres@127.0.0.1:{}/postgres", "postgres://postgres:postgres@127.0.0.1:{}/postgres",
container.get_host_port_ipv4(5432).await? container
.get_host_port_ipv4(TEST_CONTAINERS_INTERNAL_PORT)
.await?
); );
let pool = create_pool_from_url(connection_string)?; let pool = create_pool_from_url(connection_string)?;
Ok(TestContainer::new(container, pool)) Ok(TestContainer::new(container, pool))
@ -36,4 +41,5 @@ pub enum ContainerError {
BuildError(BuildError), BuildError(BuildError),
PoolError(PoolError), PoolError(PoolError),
DieselError(DieselError), DieselError(DieselError),
JoinError(JoinError),
} }