Skip to content

Commit f574993

Browse files
committed
controllers/user/update: Reduce spawn_blocking() scope
The email sending code is still sync and needs to be in a `spawn_blocking()` block for now, but the rest of the `regenerate_token_and_send()` can be converted to use async database queries.
1 parent d169e3d commit f574993

File tree

1 file changed

+31
-24
lines changed

1 file changed

+31
-24
lines changed

src/controllers/user/update.rs

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ use crate::models::{Email, NewEmail};
55
use crate::schema::{emails, users};
66
use crate::tasks::spawn_blocking;
77
use crate::util::diesel::prelude::*;
8-
use crate::util::errors::{bad_request, server_error, AppResult};
8+
use crate::util::errors::{bad_request, server_error, AppResult, BoxedAppError};
99
use axum::extract::Path;
1010
use axum::response::Response;
1111
use axum::Json;
1212
use diesel::dsl::sql;
1313
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
14+
use diesel_async::scoped_futures::ScopedFutureExt;
15+
use diesel_async::AsyncConnection;
1416
use http::request::Parts;
1517
use lettre::Address;
1618
use secrecy::{ExposeSecret, SecretString};
@@ -120,39 +122,44 @@ pub async fn regenerate_token_and_send(
120122
Path(param_user_id): Path<i32>,
121123
req: Parts,
122124
) -> AppResult<Response> {
125+
use diesel_async::RunQueryDsl;
126+
123127
let mut conn = state.db_write().await?;
124128
let auth = AuthCheck::default().check(&req, &mut conn).await?;
125-
spawn_blocking(move || {
126-
use diesel::RunQueryDsl;
127129

128-
let conn: &mut AsyncConnectionWrapper<_> = &mut conn.into();
129-
130-
let user = auth.user();
131-
132-
// need to check if current user matches user to be updated
133-
if user.id != param_user_id {
134-
return Err(bad_request("current user does not match requested user"));
135-
}
130+
// need to check if current user matches user to be updated
131+
if auth.user_id() != param_user_id {
132+
return Err(bad_request("current user does not match requested user"));
133+
}
136134

137-
conn.transaction(|conn| -> AppResult<_> {
138-
let email: Email = diesel::update(Email::belonging_to(user))
135+
conn.transaction(|conn| {
136+
async move {
137+
let email: Email = diesel::update(Email::belonging_to(auth.user()))
139138
.set(emails::token.eq(sql("DEFAULT")))
140139
.get_result(conn)
140+
.await
141141
.optional()?
142142
.ok_or_else(|| bad_request("Email could not be found"))?;
143143

144-
let email1 = UserConfirmEmail {
145-
user_name: &user.gh_login,
146-
domain: &state.emails.domain,
147-
token: email.token,
148-
};
149-
150-
state.emails.send(&email.email, email1).map_err(Into::into)
151-
})?;
152-
153-
ok_true()
144+
spawn_blocking(move || {
145+
let email1 = UserConfirmEmail {
146+
user_name: &auth.user().gh_login,
147+
domain: &state.emails.domain,
148+
token: email.token,
149+
};
150+
151+
state
152+
.emails
153+
.send(&email.email, email1)
154+
.map_err(BoxedAppError::from)
155+
})
156+
.await
157+
}
158+
.scope_boxed()
154159
})
155-
.await
160+
.await?;
161+
162+
ok_true()
156163
}
157164

158165
pub struct UserConfirmEmail<'a> {

0 commit comments

Comments
 (0)