If a function can be called with a transaction or a direct connection (and so it should start a new transaction from there because it needs one) what do you suggest to use?
Example code:
async fn find_player_id_and_assign_goal(
&self,
db: Option<&mut sqlx::PgConnection>,
id: &str,
team_id: &str,
) -> Result<String, Error> {
let mut tx = None;
let db = match db {
Some(db) => {
// I need to detect if `db` here is already a transaction or not, in which case I should start a new one:
db
},
None => &mut *tx.insert(self.pool.begin().await?),
};
let _ = self.team_service.find_team_id(Some(db), team_id).await?;
let player_id = self.repo.find_player_id(Some(db), id).await?;
self.goal_service.assign_to_player(Some(db), id).await?;
if let Some(tx) = tx {
tx.commit().await?;
}
Ok(player_id)
}
This can work, but I only have one issue:
If Some(db) => db
I need to detect there if we're already in a transaction (if db
is one). If not I should start a new one.
Do you think is there a better way to accomplish this?
If your inner calls to find_team_id
, find_player_id
, and assign_to_player
need to be in a transaction together, then just make a transaction. Nested transactions are supported so it doesn't matter if db
is already in a transaction or not.
async fn find_player_id_and_assign_goal(
&self,
db: Option<&mut sqlx::PgConnection>,
id: &str,
team_id: &str,
) -> Result<String, Error> {
let mut tx = match db {
Some(db) => db.begin().await?,
None => self.pool.begin().await?,
};
let _ = self.team_service.find_team_id(Some(&mut *tx), team_id).await?;
let player_id = self.repo.find_player_id(Some(&mut *tx), id).await?;
self.goal_service.assign_to_player(Some(&mut *tx), id).await?;
tx.commit().await?;
Ok(player_id)
}