I'm using the below code in my project (obviously across many modules).
Why the below error? I cannot understand how to fix it.
use std::{future::Future, pin::Pin, sync::Arc};
pub trait Trait: Send + Sync + Player + Shirt {}
impl<T: Player + Shirt> Trait for T {}
#[async_trait::async_trait]
pub trait Player: Send + Sync {
async fn player_create<'a>(
&'a self,
input: &PlayerInput,
lambda: &Lambda<PlayerCreateLambdaArgs, DomainPlayer>,
) -> Result<DomainPlayer, String>;
}
#[async_trait::async_trait]
pub trait Shirt: Send + Sync {
async fn shirt_get_next_and_increase<'a>(
&'a self,
_db_tx: String,
model: String,
) -> Result<i64, String>;
}
pub struct Repo {
pub pool: Arc<String>,
}
impl Repo {
pub fn new(pool: Arc<String>) -> Self {
Self { pool }
}
}
#[async_trait::async_trait]
impl Player for Repo {
async fn player_create(
&self,
_input: &PlayerInput,
lambda: &Lambda<PlayerCreateLambdaArgs, DomainPlayer>,
) -> Result<DomainPlayer, String> {
// use _input here
// let new db_tx here
let domain_player = lambda(PlayerCreateLambdaArgs {
shirt_next_value: Box::new(|model: String| {
Box::pin(self::Shirt::shirt_get_next_and_increase(
self,
"fake_db_tx".to_string(),
model,
))
}),
})
.await?;
let res = DomainPlayer {
id: domain_player.id,
shirt_number: domain_player.shirt_number,
};
Ok(res)
}
}
#[async_trait::async_trait]
impl Shirt for Repo {
async fn shirt_get_next_and_increase(
&self,
_db_tx: String,
_model: String,
) -> Result<i64, String> {
// Here I'm awaiting an async call for DB operations using the same DB transacion of the caller (db_tx)...
let res = 123;
Ok(res)
}
}
pub type Lambda<'a, ArgT, ResT> =
dyn 'a + Fn(ArgT) -> Pin<Box<dyn Future<Output = Result<ResT, String>> + Send + 'a>> + Sync;
pub struct Needs {
pub command_pg_repo: Arc<dyn Trait>,
}
#[derive(Default)]
pub struct PlayerInput {
pub id: String,
}
#[derive(Debug, Default, Clone)]
pub struct DomainPlayer {
pub id: String,
pub shirt_number: i64,
}
pub struct PlayerCreateLambdaArgs {
// other needed fields here
pub shirt_next_value: Box<
dyn Fn(String) -> Pin<Box<dyn Future<Output = Result<i64, String>> + Send>> + Send + Sync,
>,
}
pub struct Handler {
needs: Arc<Needs>,
}
impl Handler {
pub fn new(needs: Arc<Needs>) -> Self {
Self { needs }
}
pub async fn handle(&self, input: &PlayerInput) -> Result<DomainPlayer, String> {
let res = self
.needs
.command_pg_repo
.player_create(&input, &|args| {
let input = input;
Box::pin(async move {
let shirt_number = (args.shirt_next_value)("player".to_string()).await?;
let o = DomainPlayer {
id: input.id.to_string(),
shirt_number,
};
Ok(o)
})
})
.await?;
Ok(res)
}
}
#[tokio::main]
async fn main() -> Result<(), String> {
let pg_repo = Arc::new(Repo::new(Arc::new("fake DB pool".to_string())));
let needs = Arc::new(Needs {
command_pg_repo: pg_repo,
});
let handler = Handler::new(needs);
let new_player_input = PlayerInput {
id: "abc".to_string(),
};
let player = handler.handle(&new_player_input).await?;
dbg!(player);
Ok(())
}
The error:
Compiling playground v0.0.1 (/playground)
error: lifetime may not live long enough
--> src/main.rs:47:31
|
37 | async fn player_create(
| ----- lifetime `'life0` defined here
...
47 | shirt_next_value: Box::new(|model: String| {
| _______________________________^
48 | | Box::pin(self::Shirt::shirt_get_next_and_increase(
49 | | self,
50 | | "fake_db_tx".to_string(),
51 | | model,
52 | | ))
53 | | }),
| |______________^ cast requires that `'life0` must outlive `'static`
error: could not compile `playground` due to previous error