I am trying to write some code like below. The idea here is that the execute_transaction
method will take an async closure as argument. The async closure takes two arguments - one id shared reference to AppDatabase
itself and another is exclusive reference to DatabaseSession
. The execute_transaction
method creates the DatabaseSession
object. Pass it on to the closure. Once the closure returns it either commits or aborts transaction. So that way the DatabaseSession
is created and destroyed within execute_transaction
method. Below is the code I came up with but it giving me following error.
#[tokio::main]
async fn main() {
println!("Hello, world!");
let db = AppDatabase(0);
let r = db
.execute_transaction(|db, session| async {
let val = 5;
db.insert_with_session(val, session).await
})
.await;
println!("{:?}", r);
}
struct AppDatabase(i32);
struct DatabaseSession(i32);
impl AppDatabase {
async fn execute_transaction<'a, 'b, F, Fut>(&'a self, f: F) -> anyhow::Result<()>
where
F: Fn(&'a AppDatabase, &'b mut DatabaseSession) -> Fut,
Fut: std::future::Future<Output = anyhow::Result<()>> + 'a,
'a: 'b,
{
let mut session = DatabaseSession(0);
let result = f(&self, &mut session).await;
if result.is_err() {
// session.abort();
println!("rollback transaction here");
} else {
// session.commit();
println!("commit transaction here");
}
Ok(())
}
async fn insert_with_session(
&self,
val: i32,
session: &mut DatabaseSession,
) -> anyhow::Result<()> {
println!("some dummy insert operation here");
session.0 = val;
Ok(())
}
}
error[E0597]: `session` does not live long enough
--> src/main.rs:25:31
|
18 | async fn execute_transaction<'a, 'b, F, Fut>(&'a self, f: F) -> anyhow::Result<()>
| -- lifetime `'b` defined here
...
25 | let result = f(&self, &mut session).await;
| ---------^^^^^^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `session` is borrowed for `'b`
...
32 | }
| - `session` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
error: could not compile `async-callback` due to previous error
session
variable gets dropped at line 32. Which is what I want. But why compiler thinks that it is still being borrowed beyond that point?
What would be the correct way to implement my scenario here?