Skip to content

Commit 2809a21

Browse files
authored
controllers/user/update: Reduce spawn_blocking() scope (#9879)
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 9393e1b commit 2809a21

File tree

1 file changed

+29
-23
lines changed

1 file changed

+29
-23
lines changed

src/controllers/user/resend.rs

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ use crate::auth::AuthCheck;
44
use crate::controllers::helpers::ok_true;
55
use crate::models::Email;
66
use crate::tasks::spawn_blocking;
7-
use crate::util::errors::bad_request;
87
use crate::util::errors::AppResult;
8+
use crate::util::errors::{bad_request, BoxedAppError};
99
use axum::extract::Path;
1010
use axum::response::Response;
1111
use crates_io_database::schema::emails;
1212
use diesel::dsl::sql;
1313
use diesel::prelude::*;
14-
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
14+
use diesel_async::scoped_futures::ScopedFutureExt;
15+
use diesel_async::{AsyncConnection, RunQueryDsl};
1516
use http::request::Parts;
1617

1718
/// Handles `PUT /user/:user_id/resend` route
@@ -22,35 +23,40 @@ pub async fn regenerate_token_and_send(
2223
) -> AppResult<Response> {
2324
let mut conn = state.db_write().await?;
2425
let auth = AuthCheck::default().check(&req, &mut conn).await?;
25-
spawn_blocking(move || {
26-
let conn: &mut AsyncConnectionWrapper<_> = &mut conn.into();
2726

28-
let user = auth.user();
29-
30-
// need to check if current user matches user to be updated
31-
if user.id != param_user_id {
32-
return Err(bad_request("current user does not match requested user"));
33-
}
27+
// need to check if current user matches user to be updated
28+
if auth.user_id() != param_user_id {
29+
return Err(bad_request("current user does not match requested user"));
30+
}
3431

35-
conn.transaction(|conn| -> AppResult<_> {
36-
let email: Email = diesel::update(Email::belonging_to(user))
32+
conn.transaction(|conn| {
33+
async move {
34+
let email: Email = diesel::update(Email::belonging_to(auth.user()))
3735
.set(emails::token.eq(sql("DEFAULT")))
3836
.get_result(conn)
37+
.await
3938
.optional()?
4039
.ok_or_else(|| bad_request("Email could not be found"))?;
4140

42-
let email1 = UserConfirmEmail {
43-
user_name: &user.gh_login,
44-
domain: &state.emails.domain,
45-
token: email.token,
46-
};
47-
48-
state.emails.send(&email.email, email1).map_err(Into::into)
49-
})?;
50-
51-
ok_true()
41+
spawn_blocking(move || {
42+
let email1 = UserConfirmEmail {
43+
user_name: &auth.user().gh_login,
44+
domain: &state.emails.domain,
45+
token: email.token,
46+
};
47+
48+
state
49+
.emails
50+
.send(&email.email, email1)
51+
.map_err(BoxedAppError::from)
52+
})
53+
.await
54+
}
55+
.scope_boxed()
5256
})
53-
.await
57+
.await?;
58+
59+
ok_true()
5460
}
5561

5662
#[cfg(test)]

0 commit comments

Comments
 (0)