Skip to content

Commit c757675

Browse files
authored
Merge pull request #209 from weiznich/drop_async_trait
Drop async_trait
2 parents 780b348 + 6250cee commit c757675

File tree

14 files changed

+186
-140
lines changed

14 files changed

+186
-140
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ description = "An async extension for Diesel the safe, extensible ORM and Query
1313
rust-version = "1.78.0"
1414

1515
[dependencies]
16-
async-trait = "0.1.66"
1716
futures-channel = { version = "0.3.17", default-features = false, features = [
1817
"std",
1918
"sink",
@@ -30,6 +29,7 @@ mysql_async = { version = "0.34", optional = true, default-features = false, fea
3029
mysql_common = { version = "0.32", optional = true, default-features = false }
3130

3231
bb8 = { version = "0.9", optional = true }
32+
async-trait = { version = "0.1.66", optional = true }
3333
deadpool = { version = "0.12", optional = true, default-features = false, features = [
3434
"managed",
3535
] }
@@ -80,7 +80,7 @@ sync-connection-wrapper = ["tokio/rt"]
8080
async-connection-wrapper = ["tokio/net"]
8181
pool = []
8282
r2d2 = ["pool", "diesel/r2d2"]
83-
bb8 = ["pool", "dep:bb8"]
83+
bb8 = ["pool", "dep:bb8", "dep:async-trait"]
8484
mobc = ["pool", "dep:mobc"]
8585
deadpool = ["pool", "dep:deadpool"]
8686

src/async_connection_wrapper.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ mod implementation {
234234
runtime: &'a B,
235235
}
236236

237-
impl<'a, S, B> Iterator for AsyncCursorWrapper<'a, S, B>
237+
impl<S, B> Iterator for AsyncCursorWrapper<'_, S, B>
238238
where
239239
S: Stream,
240240
B: BlockOn,

src/lib.rs

+51-37
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@
7676
use diesel::backend::Backend;
7777
use diesel::connection::{CacheSize, Instrumentation};
7878
use diesel::query_builder::{AsQuery, QueryFragment, QueryId};
79-
use diesel::result::Error;
8079
use diesel::row::Row;
8180
use diesel::{ConnectionResult, QueryResult};
82-
use futures_util::{Future, Stream};
81+
use futures_util::future::BoxFuture;
82+
use futures_util::{Future, FutureExt, Stream};
8383
use std::fmt::Debug;
8484

8585
pub use scoped_futures;
@@ -115,21 +115,19 @@ pub use self::transaction_manager::{AnsiTransactionManager, TransactionManager};
115115
/// Perform simple operations on a backend.
116116
///
117117
/// You should likely use [`AsyncConnection`] instead.
118-
#[async_trait::async_trait]
119118
pub trait SimpleAsyncConnection {
120119
/// Execute multiple SQL statements within the same string.
121120
///
122121
/// This function is used to execute migrations,
123122
/// which may contain more than one SQL statement.
124-
async fn batch_execute(&mut self, query: &str) -> QueryResult<()>;
123+
fn batch_execute(&mut self, query: &str) -> impl Future<Output = QueryResult<()>> + Send;
125124
}
126125

127126
/// An async connection to a database
128127
///
129128
/// This trait represents a n async database connection. It can be used to query the database through
130129
/// the query dsl provided by diesel, custom extensions or raw sql queries. It essentially mirrors
131130
/// the sync diesel [`Connection`](diesel::connection::Connection) implementation
132-
#[async_trait::async_trait]
133131
pub trait AsyncConnection: SimpleAsyncConnection + Sized + Send {
134132
/// The future returned by `AsyncConnection::execute`
135133
type ExecuteFuture<'conn, 'query>: Future<Output = QueryResult<usize>> + Send;
@@ -151,7 +149,7 @@ pub trait AsyncConnection: SimpleAsyncConnection + Sized + Send {
151149
/// The argument to this method and the method's behavior varies by backend.
152150
/// See the documentation for that backend's connection class
153151
/// for details about what it accepts and how it behaves.
154-
async fn establish(database_url: &str) -> ConnectionResult<Self>;
152+
fn establish(database_url: &str) -> impl Future<Output = ConnectionResult<Self>> + Send;
155153

156154
/// Executes the given function inside of a database transaction
157155
///
@@ -230,34 +228,44 @@ pub trait AsyncConnection: SimpleAsyncConnection + Sized + Send {
230228
/// # Ok(())
231229
/// # }
232230
/// ```
233-
async fn transaction<'a, R, E, F>(&mut self, callback: F) -> Result<R, E>
231+
fn transaction<'a, 'conn, R, E, F>(
232+
&'conn mut self,
233+
callback: F,
234+
) -> BoxFuture<'conn, Result<R, E>>
235+
// we cannot use `impl Trait` here due to bugs in rustc
236+
// https://github.com/rust-lang/rust/issues/100013
237+
//impl Future<Output = Result<R, E>> + Send + 'async_trait
234238
where
235239
F: for<'r> FnOnce(&'r mut Self) -> ScopedBoxFuture<'a, 'r, Result<R, E>> + Send + 'a,
236240
E: From<diesel::result::Error> + Send + 'a,
237241
R: Send + 'a,
242+
'a: 'conn,
238243
{
239-
Self::TransactionManager::transaction(self, callback).await
244+
Self::TransactionManager::transaction(self, callback).boxed()
240245
}
241246

242247
/// Creates a transaction that will never be committed. This is useful for
243248
/// tests. Panics if called while inside of a transaction or
244249
/// if called with a connection containing a broken transaction
245-
async fn begin_test_transaction(&mut self) -> QueryResult<()> {
250+
fn begin_test_transaction(&mut self) -> impl Future<Output = QueryResult<()>> + Send {
246251
use diesel::connection::TransactionManagerStatus;
247252

248-
match Self::TransactionManager::transaction_manager_status_mut(self) {
249-
TransactionManagerStatus::Valid(valid_status) => {
250-
assert_eq!(None, valid_status.transaction_depth())
251-
}
252-
TransactionManagerStatus::InError => panic!("Transaction manager in error"),
253-
};
254-
Self::TransactionManager::begin_transaction(self).await?;
255-
// set the test transaction flag
256-
// to prevent that this connection gets dropped in connection pools
257-
// Tests commonly set the poolsize to 1 and use `begin_test_transaction`
258-
// to prevent modifications to the schema
259-
Self::TransactionManager::transaction_manager_status_mut(self).set_test_transaction_flag();
260-
Ok(())
253+
async {
254+
match Self::TransactionManager::transaction_manager_status_mut(self) {
255+
TransactionManagerStatus::Valid(valid_status) => {
256+
assert_eq!(None, valid_status.transaction_depth())
257+
}
258+
TransactionManagerStatus::InError => panic!("Transaction manager in error"),
259+
};
260+
Self::TransactionManager::begin_transaction(self).await?;
261+
// set the test transaction flag
262+
// to prevent that this connection gets dropped in connection pools
263+
// Tests commonly set the poolsize to 1 and use `begin_test_transaction`
264+
// to prevent modifications to the schema
265+
Self::TransactionManager::transaction_manager_status_mut(self)
266+
.set_test_transaction_flag();
267+
Ok(())
268+
}
261269
}
262270

263271
/// Executes the given function inside a transaction, but does not commit
@@ -297,27 +305,33 @@ pub trait AsyncConnection: SimpleAsyncConnection + Sized + Send {
297305
/// # Ok(())
298306
/// # }
299307
/// ```
300-
async fn test_transaction<'a, R, E, F>(&'a mut self, f: F) -> R
308+
fn test_transaction<'conn, 'a, R, E, F>(
309+
&'conn mut self,
310+
f: F,
311+
) -> impl Future<Output = R> + Send + 'conn
301312
where
302313
F: for<'r> FnOnce(&'r mut Self) -> ScopedBoxFuture<'a, 'r, Result<R, E>> + Send + 'a,
303314
E: Debug + Send + 'a,
304315
R: Send + 'a,
305-
Self: 'a,
316+
'a: 'conn,
306317
{
307318
use futures_util::TryFutureExt;
308-
309-
let mut user_result = None;
310-
let _ = self
311-
.transaction::<R, _, _>(|c| {
312-
f(c).map_err(|_| Error::RollbackTransaction)
313-
.and_then(|r| {
314-
user_result = Some(r);
315-
futures_util::future::ready(Err(Error::RollbackTransaction))
316-
})
317-
.scope_boxed()
318-
})
319-
.await;
320-
user_result.expect("Transaction did not succeed")
319+
let (user_result_tx, user_result_rx) = std::sync::mpsc::channel();
320+
self.transaction::<R, _, _>(move |conn| {
321+
f(conn)
322+
.map_err(|_| diesel::result::Error::RollbackTransaction)
323+
.and_then(move |r| {
324+
let _ = user_result_tx.send(r);
325+
futures_util::future::ready(Err(diesel::result::Error::RollbackTransaction))
326+
})
327+
.scope_boxed()
328+
})
329+
.then(move |_r| {
330+
let r = user_result_rx
331+
.try_recv()
332+
.expect("Transaction did not succeed");
333+
futures_util::future::ready(r)
334+
})
321335
}
322336

323337
#[doc(hidden)]

src/mysql/mod.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ pub struct AsyncMysqlConnection {
3434
instrumentation: DynInstrumentation,
3535
}
3636

37-
#[async_trait::async_trait]
3837
impl SimpleAsyncConnection for AsyncMysqlConnection {
3938
async fn batch_execute(&mut self, query: &str) -> diesel::QueryResult<()> {
4039
self.instrumentation()
@@ -63,7 +62,6 @@ const CONNECTION_SETUP_QUERIES: &[&str] = &[
6362
"SET character_set_results = 'utf8mb4'",
6463
];
6564

66-
#[async_trait::async_trait]
6765
impl AsyncConnection for AsyncMysqlConnection {
6866
type ExecuteFuture<'conn, 'query> = BoxFuture<'conn, QueryResult<usize>>;
6967
type LoadFuture<'conn, 'query> = BoxFuture<'conn, QueryResult<Self::Stream<'conn, 'query>>>;
@@ -208,9 +206,9 @@ fn update_transaction_manager_status<T>(
208206
query_result
209207
}
210208

211-
fn prepare_statement_helper<'a, 'b>(
209+
fn prepare_statement_helper<'a>(
212210
conn: &'a mut mysql_async::Conn,
213-
sql: &'b str,
211+
sql: &str,
214212
_is_for_cache: diesel::connection::statement_cache::PrepareForCache,
215213
_metadata: &[MysqlType],
216214
) -> CallbackHelper<impl Future<Output = QueryResult<(Statement, &'a mut mysql_async::Conn)>> + Send>

src/mysql/row.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ pub struct MysqlField<'a> {
132132
name: Cow<'a, str>,
133133
}
134134

135-
impl<'a> diesel::row::Field<'a, Mysql> for MysqlField<'_> {
135+
impl diesel::row::Field<'_, Mysql> for MysqlField<'_> {
136136
fn field_name(&self) -> Option<&str> {
137137
Some(&*self.name)
138138
}

src/pg/mod.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ pub struct AsyncPgConnection {
133133
instrumentation: Arc<std::sync::Mutex<DynInstrumentation>>,
134134
}
135135

136-
#[async_trait::async_trait]
137136
impl SimpleAsyncConnection for AsyncPgConnection {
138137
async fn batch_execute(&mut self, query: &str) -> QueryResult<()> {
139138
self.record_instrumentation(InstrumentationEvent::start_query(&StrQueryHelper::new(
@@ -154,7 +153,6 @@ impl SimpleAsyncConnection for AsyncPgConnection {
154153
}
155154
}
156155

157-
#[async_trait::async_trait]
158156
impl AsyncConnection for AsyncPgConnection {
159157
type LoadFuture<'conn, 'query> = BoxFuture<'query, QueryResult<Self::Stream<'conn, 'query>>>;
160158
type ExecuteFuture<'conn, 'query> = BoxFuture<'query, QueryResult<usize>>;
@@ -306,9 +304,9 @@ fn update_transaction_manager_status<T>(
306304
query_result
307305
}
308306

309-
fn prepare_statement_helper<'a>(
307+
fn prepare_statement_helper(
310308
conn: Arc<tokio_postgres::Client>,
311-
sql: &'a str,
309+
sql: &str,
312310
_is_for_cache: PrepareForCache,
313311
metadata: &[PgTypeMetadata],
314312
) -> CallbackHelper<

src/pg/transaction_builder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ where
310310
}
311311
}
312312

313-
impl<'a, C> QueryFragment<Pg> for TransactionBuilder<'a, C> {
313+
impl<C> QueryFragment<Pg> for TransactionBuilder<'_, C> {
314314
fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> {
315315
out.push_sql("BEGIN TRANSACTION");
316316
if let Some(ref isolation_level) = self.isolation_level {

src/pooled_connection/bb8.rs

-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
//! # Ok(())
5151
//! # }
5252
//! ```
53-
5453
use super::{AsyncDieselConnectionManager, PoolError, PoolableConnection};
5554
use bb8::ManageConnection;
5655
use diesel::query_builder::QueryFragment;

src/pooled_connection/mod.rs

+26-19
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ use crate::{TransactionManager, UpdateAndFetchResults};
1010
use diesel::associations::HasTable;
1111
use diesel::connection::{CacheSize, Instrumentation};
1212
use diesel::QueryResult;
13+
use futures_util::future::BoxFuture;
1314
use futures_util::{future, FutureExt};
1415
use std::borrow::Cow;
1516
use std::fmt;
17+
use std::future::Future;
1618
use std::ops::DerefMut;
1719

1820
#[cfg(feature = "bb8")]
@@ -164,7 +166,6 @@ where
164166
}
165167
}
166168

167-
#[async_trait::async_trait]
168169
impl<C> SimpleAsyncConnection for C
169170
where
170171
C: DerefMut + Send,
@@ -176,7 +177,6 @@ where
176177
}
177178
}
178179

179-
#[async_trait::async_trait]
180180
impl<C> AsyncConnection for C
181181
where
182182
C: DerefMut + Send,
@@ -251,7 +251,6 @@ where
251251
#[allow(missing_debug_implementations)]
252252
pub struct PoolTransactionManager<TM>(std::marker::PhantomData<TM>);
253253

254-
#[async_trait::async_trait]
255254
impl<C, TM> TransactionManager<C> for PoolTransactionManager<TM>
256255
where
257256
C: DerefMut + Send,
@@ -283,18 +282,22 @@ where
283282
}
284283
}
285284

286-
#[async_trait::async_trait]
287285
impl<Changes, Output, Conn> UpdateAndFetchResults<Changes, Output> for Conn
288286
where
289287
Conn: DerefMut + Send,
290288
Changes: diesel::prelude::Identifiable + HasTable + Send,
291289
Conn::Target: UpdateAndFetchResults<Changes, Output>,
292290
{
293-
async fn update_and_fetch(&mut self, changeset: Changes) -> QueryResult<Output>
291+
fn update_and_fetch<'conn, 'changes>(
292+
&'conn mut self,
293+
changeset: Changes,
294+
) -> BoxFuture<'changes, QueryResult<Output>>
294295
where
295-
Changes: 'async_trait,
296+
Changes: 'changes,
297+
'conn: 'changes,
298+
Self: 'changes,
296299
{
297-
self.deref_mut().update_and_fetch(changeset).await
300+
self.deref_mut().update_and_fetch(changeset)
298301
}
299302
}
300303

@@ -321,13 +324,15 @@ impl diesel::query_builder::Query for CheckConnectionQuery {
321324
impl<C> diesel::query_dsl::RunQueryDsl<C> for CheckConnectionQuery {}
322325

323326
#[doc(hidden)]
324-
#[async_trait::async_trait]
325327
pub trait PoolableConnection: AsyncConnection {
326328
/// Check if a connection is still valid
327329
///
328330
/// The default implementation will perform a check based on the provided
329331
/// recycling method variant
330-
async fn ping(&mut self, config: &RecyclingMethod<Self>) -> diesel::QueryResult<()>
332+
fn ping(
333+
&mut self,
334+
config: &RecyclingMethod<Self>,
335+
) -> impl Future<Output = diesel::QueryResult<()>> + Send
331336
where
332337
for<'a> Self: 'a,
333338
diesel::dsl::select<diesel::dsl::AsExprOf<i32, diesel::sql_types::Integer>>:
@@ -337,19 +342,21 @@ pub trait PoolableConnection: AsyncConnection {
337342
use crate::run_query_dsl::RunQueryDsl;
338343
use diesel::IntoSql;
339344

340-
match config {
341-
RecyclingMethod::Fast => Ok(()),
342-
RecyclingMethod::Verified => {
343-
diesel::select(1_i32.into_sql::<diesel::sql_types::Integer>())
345+
async move {
346+
match config {
347+
RecyclingMethod::Fast => Ok(()),
348+
RecyclingMethod::Verified => {
349+
diesel::select(1_i32.into_sql::<diesel::sql_types::Integer>())
350+
.execute(self)
351+
.await
352+
.map(|_| ())
353+
}
354+
RecyclingMethod::CustomQuery(query) => diesel::sql_query(query.as_ref())
344355
.execute(self)
345356
.await
346-
.map(|_| ())
357+
.map(|_| ()),
358+
RecyclingMethod::CustomFunction(c) => c(self).await,
347359
}
348-
RecyclingMethod::CustomQuery(query) => diesel::sql_query(query.as_ref())
349-
.execute(self)
350-
.await
351-
.map(|_| ()),
352-
RecyclingMethod::CustomFunction(c) => c(self).await,
353360
}
354361
}
355362

0 commit comments

Comments
 (0)