diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2024-10-11 21:19:45 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2024-10-11 21:19:45 -0400 |
| commit | a0abed5ea08b2fc5b9ac4abdade1199f62cd5da7 (patch) | |
| tree | fcb7d50dc1a80d79da5a088f82cd1f42b6b3084d /src | |
| parent | 864febeefc5213928bf88f89a714a006326e5b41 (diff) | |
Split the login transaction, to reduce database contention during login
Diffstat (limited to 'src')
| -rw-r--r-- | src/login/history.rs | 3 | ||||
| -rw-r--r-- | src/login/snapshot.rs | 3 | ||||
| -rw-r--r-- | src/token/app.rs | 13 |
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) } |
