summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2024-10-11 21:19:45 -0400
committerOwen Jacobson <owen@grimoire.ca>2024-10-11 21:19:45 -0400
commita0abed5ea08b2fc5b9ac4abdade1199f62cd5da7 (patch)
treefcb7d50dc1a80d79da5a088f82cd1f42b6b3084d /src
parent864febeefc5213928bf88f89a714a006326e5b41 (diff)
Split the login transaction, to reduce database contention during login
Diffstat (limited to 'src')
-rw-r--r--src/login/history.rs3
-rw-r--r--src/login/snapshot.rs3
-rw-r--r--src/token/app.rs13
3 files changed, 14 insertions, 5 deletions
diff --git a/src/login/history.rs b/src/login/history.rs
index add7d1e..f8d81bb 100644
--- a/src/login/history.rs
+++ b/src/login/history.rs
@@ -18,7 +18,8 @@ impl History {
// Snapshot of this login as it was when created. (Note to the future: it's okay
// if this returns a redacted or modified version of the login. If we implement
- // renames by redacting the original name, then this should return the edited login, not the original, even if that's not how it was "as created.")
+ // renames by redacting the original name, then this should return the edited
+ // login, not the original, even if that's not how it was "as created.")
#[cfg(test)]
pub fn as_created(&self) -> Login {
self.login.clone()
diff --git a/src/login/snapshot.rs b/src/login/snapshot.rs
index 1379005..1a92f5c 100644
--- a/src/login/snapshot.rs
+++ b/src/login/snapshot.rs
@@ -19,7 +19,8 @@ pub struct Login {
impl Login {
// Two reasons for this allow:
//
- // 1. This is used to collect streams using a fold, below, which requires a type consistent with the fold, and
+ // 1. This is used to collect streams using a fold, below, which requires a type
+ // consistent with the fold, and
// 2. It's also consistent with the other history state machine types.
#[allow(clippy::unnecessary_wraps)]
fn apply(state: Option<Self>, event: Event) -> Option<Self> {
diff --git a/src/token/app.rs b/src/token/app.rs
index 04f8747..15fd858 100644
--- a/src/token/app.rs
+++ b/src/token/app.rs
@@ -38,15 +38,22 @@ impl<'a> Tokens<'a> {
.await
.optional()?
.ok_or(LoginError::Rejected)?;
+ // Split the transaction here to avoid holding the tx open (potentially blocking
+ // other writes) while we do the fairly expensive task of verifying the
+ // password. It's okay if the token issuance transaction happens some notional
+ // amount of time after retrieving the login, as inserting the token will fail
+ // if the account is deleted during that time.
+ tx.commit().await?;
let token = if stored_hash.verify(password)? {
- tx.tokens().issue(&login, login_at).await?
+ let mut tx = self.db.begin().await?;
+ let token = tx.tokens().issue(&login, login_at).await?;
+ tx.commit().await?;
+ token
} else {
Err(LoginError::Rejected)?
};
- tx.commit().await?;
-
Ok(token)
}