Skip to content

Commit 33fbb4b

Browse files
prestwichclaude
andcommitted
fix(storage): desugar async fn in ColdConnect trait to specify Send bound
Addresses async-fn-in-trait clippy lint by explicitly desugaring async fn to return impl Future + Send. This makes the Send bound explicit and allows callers to know the future can be sent across threads. Changes: - Desugar ColdConnect::connect to return impl Future + Send - Add #[allow(clippy::manual_async_fn)] to MDBX and EitherCold impls - Fix redundant closures in error mapping - Add Debug derive to StorageBuilder - Add serial_test to workspace for test isolation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a723304 commit 33fbb4b

File tree

7 files changed

+35
-20
lines changed

7 files changed

+35
-20
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ parking_lot = "0.12.5"
6666
rand = "0.9.2"
6767
rayon = "1.10"
6868
serde = { version = "1.0.217", features = ["derive"] }
69+
serial_test = "3.3"
6970
tempfile = "3.20.0"
7071
thiserror = "2.0.18"
7172
tokio = { version = "1.45.0", features = ["full"] }

crates/cold-mdbx/src/connector.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,11 @@ impl ColdConnect for MdbxConnector {
106106
type Cold = MdbxColdBackend;
107107
type Error = MdbxColdError;
108108

109-
async fn connect(&self) -> Result<Self::Cold, Self::Error> {
109+
#[allow(clippy::manual_async_fn)]
110+
fn connect(&self) -> impl std::future::Future<Output = Result<Self::Cold, Self::Error>> + Send {
110111
// MDBX open is sync, but wrapped in async for trait consistency
111112
// Opens read-write and creates tables
112-
MdbxColdBackend::open_rw(&self.path)
113+
let path = self.path.clone();
114+
async move { MdbxColdBackend::open_rw(&path) }
113115
}
114116
}

crates/cold-sql/src/connector.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ impl ColdConnect for SqlConnector {
7676
type Cold = SqlColdBackend;
7777
type Error = SqlColdError;
7878

79-
async fn connect(&self) -> Result<Self::Cold, Self::Error> {
80-
SqlColdBackend::connect(&self.url).await
79+
fn connect(&self) -> impl std::future::Future<Output = Result<Self::Cold, Self::Error>> + Send {
80+
let url = self.url.clone();
81+
async move { SqlColdBackend::connect(&url).await }
8182
}
8283
}

crates/cold/src/connect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ pub trait ColdConnect {
1717
///
1818
/// Async to support backends that require async initialization
1919
/// (like SQL connection pools).
20-
async fn connect(&self) -> Result<Self::Cold, Self::Error>;
20+
fn connect(&self) -> impl std::future::Future<Output = Result<Self::Cold, Self::Error>> + Send;
2121
}

crates/storage/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ thiserror.workspace = true
2828
tokio-util.workspace = true
2929

3030
[dev-dependencies]
31+
serial_test.workspace = true
3132
signet-storage = { path = ".", features = ["test-utils"] }
3233
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
3334
tokio-util.workspace = true

crates/storage/src/builder.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type EnvColdConnector = Either<MdbxConnector, ()>;
3939
/// .build()
4040
/// .await?;
4141
/// ```
42-
#[derive(Default)]
42+
#[derive(Default, Debug)]
4343
pub struct StorageBuilder<H = (), C = ()> {
4444
hot_connector: H,
4545
cold_connector: C,
@@ -163,8 +163,10 @@ impl StorageBuilder<MdbxConnector, EnvColdConnector> {
163163
#[cfg(test)]
164164
mod tests {
165165
use super::*;
166+
use serial_test::serial;
166167

167168
#[test]
169+
#[serial]
168170
fn from_env_missing_hot_path() {
169171
// SAFETY: Test environment
170172
unsafe {
@@ -174,6 +176,7 @@ mod tests {
174176
}
175177

176178
#[test]
179+
#[serial]
177180
fn from_env_missing_cold_backend() {
178181
// SAFETY: Test environment
179182
unsafe {
@@ -186,6 +189,7 @@ mod tests {
186189
}
187190

188191
#[test]
192+
#[serial]
189193
fn from_env_ambiguous_cold_backend() {
190194
// SAFETY: Test environment
191195
unsafe {
@@ -198,6 +202,7 @@ mod tests {
198202
}
199203

200204
#[test]
205+
#[serial]
201206
fn from_env_mdbx_cold() {
202207
// SAFETY: Test environment
203208
unsafe {

crates/storage/src/either.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ macro_rules! dispatch_async {
7171
}
7272

7373
// Implement ColdStorage for EitherCold by dispatching to inner type
74+
#[allow(clippy::manual_async_fn)]
7475
impl ColdStorage for EitherCold {
7576
fn get_header(
7677
&self,
@@ -181,15 +182,18 @@ impl ColdConnect for Either<MdbxConnector, SqlConnector> {
181182
type Cold = EitherCold;
182183
type Error = crate::StorageError;
183184

184-
async fn connect(&self) -> Result<Self::Cold, Self::Error> {
185-
match self {
186-
Either::Left(mdbx) => {
187-
let backend = mdbx.connect().await.map_err(|e| crate::StorageError::MdbxCold(e))?;
188-
Ok(EitherCold::Mdbx(backend))
189-
}
190-
Either::Right(sql) => {
191-
let backend = sql.connect().await.map_err(|e| crate::StorageError::SqlCold(e))?;
192-
Ok(EitherCold::Sql(backend))
185+
fn connect(&self) -> impl std::future::Future<Output = Result<Self::Cold, Self::Error>> + Send {
186+
let self_clone = self.clone();
187+
async move {
188+
match self_clone {
189+
Either::Left(mdbx) => {
190+
let backend = mdbx.connect().await.map_err(crate::StorageError::MdbxCold)?;
191+
Ok(EitherCold::Mdbx(backend))
192+
}
193+
Either::Right(sql) => {
194+
let backend = sql.connect().await.map_err(crate::StorageError::SqlCold)?;
195+
Ok(EitherCold::Sql(backend))
196+
}
193197
}
194198
}
195199
}
@@ -201,12 +205,13 @@ impl ColdConnect for Either<MdbxConnector, ()> {
201205
type Cold = MdbxColdBackend;
202206
type Error = crate::StorageError;
203207

204-
async fn connect(&self) -> Result<Self::Cold, Self::Error> {
205-
match self {
206-
Either::Left(mdbx) => {
207-
mdbx.connect().await.map_err(|e| crate::StorageError::MdbxCold(e))
208+
fn connect(&self) -> impl std::future::Future<Output = Result<Self::Cold, Self::Error>> + Send {
209+
let self_clone = self.clone();
210+
async move {
211+
match self_clone {
212+
Either::Left(mdbx) => mdbx.connect().await.map_err(crate::StorageError::MdbxCold),
213+
Either::Right(()) => unreachable!("SQL not enabled"),
208214
}
209-
Either::Right(()) => unreachable!("SQL not enabled"),
210215
}
211216
}
212217
}

0 commit comments

Comments
 (0)