audunhalland / entrait

Loosely coupled Rust application design made easy
83 stars 1 forks source link

Find a working design pattern for modelling transaction-like things #25

Open audunhalland opened 1 year ago

audunhalland commented 1 year ago

Database transactions require some kind of context value representing a session with the database. The transaction either succeeds or is cancelled in case of an error. In SQLx the transaction object requires a call to .commit() at the end.

Designing a DB abstraction this way requires an associated type representing the transaction object:

async fn some_db_op(deps: &impl Repository) {
     let mut tx = deps.transaction();
     deps.insert_something(some_value, &mut tx)?;
     tx.commit().await?;
     Ok(())
}

(the transaction object is likely different for each implementation of Repository).

I'm not completely sold on the need to explicitly call commit. What about taking advantage of the Result each db call returns? If it returns some kind of Result<Transaction<T>, Error>. That Ok context could be used somehow in subsequent calls. At the end of the operation chain, the T needs to be dug out from the transaction, and that's where the commit happens.

This issue represent exploring the design space around transaction modelling.