From 98f6f4eeeabdec450352ba71ff93df6e844093b6 Mon Sep 17 00:00:00 2001 From: Eric Woolsey Date: Thu, 8 Feb 2024 11:12:34 -0800 Subject: [PATCH] transactions --- src/app.rs | 33 +++++++++++++++++++-------------- src/database/mod.rs | 9 +++++++-- src/server/error.rs | 2 ++ 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/app.rs b/src/app.rs index 8bb86d6b..d4b5c298 100644 --- a/src/app.rs +++ b/src/app.rs @@ -374,14 +374,21 @@ impl App { Ok(()) } + pub async fn delete_identity(&self, commitment: &Hash) -> Result<(), ServerError> { + let mut tx = self.database.begin().await?; + self.delete_identity_tx(&mut tx, commitment).await?; + tx.commit().await?; + Ok(()) + } + /// Queues a deletion from the merkle tree. /// /// # Errors /// /// Will return `Err` if identity is already queued, not in the tree, or the /// queue malfunctions. - #[instrument(level = "debug", skip(self))] - pub async fn delete_identity( + #[instrument(level = "debug", skip(self, tx))] + pub async fn delete_identity_tx( &self, tx: &mut Transaction<'_, Postgres>, commitment: &Hash, @@ -412,11 +419,7 @@ impl App { } // Check if the id is already queued for deletion - if self - .database - .identity_is_queued_for_deletion(commitment) - .await? - { + if tx.identity_is_queued_for_deletion(commitment).await? { return Err(ServerError::IdentityQueuedForDeletion); } @@ -428,9 +431,7 @@ impl App { } // If the id has not been deleted, insert into the deletions table - self.database - .insert_new_deletion(leaf_index, commitment) - .await?; + tx.insert_new_deletion(leaf_index, commitment).await?; Ok(()) } @@ -473,17 +474,21 @@ impl App { return Err(ServerError::UnreducedCommitment); } - if self.database.identity_exists(*new_commitment).await? { + let mut tx = self.database.begin().await?; + + if tx.identity_exists(*new_commitment).await? { return Err(ServerError::DuplicateCommitment); } // Delete the existing id and insert the commitments into the recovery table - self.delete_identity(existing_commitment).await?; + self.delete_identity_tx(&mut tx, existing_commitment) + .await?; - self.database - .insert_new_recovery(existing_commitment, new_commitment) + tx.insert_new_recovery(existing_commitment, new_commitment) .await?; + tx.commit().await?; + Ok(()) } diff --git a/src/database/mod.rs b/src/database/mod.rs index 77361ee3..762eae4d 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -59,6 +59,13 @@ impl Database { // Create a connection pool let pool = PoolOptions::::new() .max_connections(config.max_connections) + .after_connect(|conn, _| { + Box::pin(async move { + conn.execute("SET DEFAULT_TRANSACTION_ISOLATION TO 'SERIALIZABLE'") + .await?; + Ok(()) + }) + }) .connect(config.database.expose()) .await .context("error connecting to database")?; @@ -188,8 +195,6 @@ impl Database { let mined_status = ProcessedStatus::Mined; let mut tx = self.pool.begin().await?; - tx.execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;") - .await?; let root_id = tx.get_id_by_root(root).await?; diff --git a/src/server/error.rs b/src/server/error.rs index e7b1533e..ed27c8db 100644 --- a/src/server/error.rs +++ b/src/server/error.rs @@ -63,6 +63,8 @@ pub enum Error { NoProversOnIdInsert, #[error("Identity Manager had no provers on point of identity deletion.")] NoProversOnIdDeletion, + #[error(transparent)] + Sqlx(#[from] sqlx::Error), #[error("The tree is uninitialized. Try again in a few moments.")] TreeStateUninitialized, #[error(transparent)]