I have services with trait like:
#[async_trait::async_trait]
pub trait ServiceOne: Send + Sync {
async fn player_update(
&self,
id: &str,
lambda: &(dyn Fn(Player) -> Result<Player> + Sync),
) -> Result<Player>;
}
which I use like this:
pub struct UpdateHandler {
service_1: Arc<dyn ServiceOne>,
service_2: Arc<dyn ServiceTwo>,
service_3: Arc<dyn ServiceThree>,
}
impl UpdateHandler {
pub fn new(
service_1: Arc<dyn ServiceOne>,
service_2: Arc<dyn ServiceTwo>,
service_3: Arc<dyn ServiceThree>,
) -> Self {
Self { service_1, service_2, service_3 }
}
pub async fn handle(&self, input: PlayerInput) -> Result<Player> {
let output = self.service_1.player_update(&input.id, & |player_from_db| {
// this closure is a DB transaction; if something fails in here everything is rolled back
let new_player = Player::update(player_from_db, input)?;
self.service_2.player_update(&input.id, &new_player).await?;
self.service_3.player_update(&input.id, &new_player).await?;
Ok(new_player)
})
.await?;
Ok(output)
}
}
I would like to know if and how to transform that closure (called lambda
) in an async one, because as you can see I need to call .await
many times in that closure.
If it's not possible is there another way to organize my code? (Among other things I also think that my lambda
definition is not totally efficient and idiomatic; by the way, do you have hints?).
I need to call those methods in the closure because that closure is a database transaction: if any service call fails that transaction is rolled back.
If there is NO way to have async closures with STABLE Rust, is there a way with UNSTABLE, nightly Rust using some feature flags?