Skip to content

Commit 818fe0a

Browse files
committed
controllers/user/me: Reduce spawn_blocking() usage
1 parent be56d69 commit 818fe0a

File tree

1 file changed

+89
-99
lines changed
  • src/controllers/user

1 file changed

+89
-99
lines changed

src/controllers/user/me.rs

Lines changed: 89 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -21,50 +21,47 @@ use crate::views::{EncodableMe, EncodablePrivateUser, EncodableVersion, OwnedCra
2121

2222
/// Handles the `GET /me` route.
2323
pub async fn me(app: AppState, req: Parts) -> AppResult<Json<EncodableMe>> {
24+
use diesel_async::RunQueryDsl;
25+
2426
let mut conn = app.db_read_prefer_primary().await?;
2527
let user_id = AuthCheck::only_cookie()
2628
.check(&req, &mut conn)
2729
.await?
2830
.user_id();
29-
spawn_blocking(move || {
30-
use diesel::RunQueryDsl;
31-
32-
let conn: &mut AsyncConnectionWrapper<_> = &mut conn.into();
31+
let (user, verified, email, verification_sent): (User, Option<bool>, Option<String>, bool) =
32+
users::table
33+
.find(user_id)
34+
.left_join(emails::table)
35+
.select((
36+
User::as_select(),
37+
emails::verified.nullable(),
38+
emails::email.nullable(),
39+
emails::token_generated_at.nullable().is_not_null(),
40+
))
41+
.first(&mut conn)
42+
.await?;
43+
44+
let owned_crates = CrateOwner::by_owner_kind(OwnerKind::User)
45+
.inner_join(crates::table)
46+
.filter(crate_owners::owner_id.eq(user_id))
47+
.select((crates::id, crates::name, crate_owners::email_notifications))
48+
.order(crates::name.asc())
49+
.load(&mut conn)
50+
.await?
51+
.into_iter()
52+
.map(|(id, name, email_notifications)| OwnedCrate {
53+
id,
54+
name,
55+
email_notifications,
56+
})
57+
.collect();
3358

34-
let (user, verified, email, verification_sent): (User, Option<bool>, Option<String>, bool) =
35-
users::table
36-
.find(user_id)
37-
.left_join(emails::table)
38-
.select((
39-
User::as_select(),
40-
emails::verified.nullable(),
41-
emails::email.nullable(),
42-
emails::token_generated_at.nullable().is_not_null(),
43-
))
44-
.first(conn)?;
45-
46-
let owned_crates = CrateOwner::by_owner_kind(OwnerKind::User)
47-
.inner_join(crates::table)
48-
.filter(crate_owners::owner_id.eq(user_id))
49-
.select((crates::id, crates::name, crate_owners::email_notifications))
50-
.order(crates::name.asc())
51-
.load(conn)?
52-
.into_iter()
53-
.map(|(id, name, email_notifications)| OwnedCrate {
54-
id,
55-
name,
56-
email_notifications,
57-
})
58-
.collect();
59-
60-
let verified = verified.unwrap_or(false);
61-
let verification_sent = verified || verification_sent;
62-
Ok(Json(EncodableMe {
63-
user: EncodablePrivateUser::from(user, email, verified, verification_sent),
64-
owned_crates,
65-
}))
66-
})
67-
.await
59+
let verified = verified.unwrap_or(false);
60+
let verification_sent = verified || verification_sent;
61+
Ok(Json(EncodableMe {
62+
user: EncodablePrivateUser::from(user, email, verified, verification_sent),
63+
owned_crates,
64+
}))
6865
}
6966

7067
/// Handles the `GET /me/updates` route.
@@ -110,29 +107,28 @@ pub async fn updates(app: AppState, req: Parts) -> AppResult<Json<Value>> {
110107

111108
/// Handles the `PUT /confirm/:email_token` route
112109
pub async fn confirm_user_email(state: AppState, Path(token): Path<String>) -> AppResult<Response> {
113-
let conn = state.db_write().await?;
114-
spawn_blocking(move || {
115-
use diesel::RunQueryDsl;
116-
117-
let conn: &mut AsyncConnectionWrapper<_> = &mut conn.into();
110+
use diesel::update;
111+
use diesel_async::RunQueryDsl;
118112

119-
use diesel::update;
113+
let mut conn = state.db_write().await?;
120114

121-
let updated_rows = update(emails::table.filter(emails::token.eq(&token)))
122-
.set(emails::verified.eq(true))
123-
.execute(conn)?;
115+
let updated_rows = update(emails::table.filter(emails::token.eq(&token)))
116+
.set(emails::verified.eq(true))
117+
.execute(&mut conn)
118+
.await?;
124119

125-
if updated_rows == 0 {
126-
return Err(bad_request("Email belonging to token not found."));
127-
}
120+
if updated_rows == 0 {
121+
return Err(bad_request("Email belonging to token not found."));
122+
}
128123

129-
ok_true()
130-
})
131-
.await
124+
ok_true()
132125
}
133126

134127
/// Handles `PUT /me/email_notifications` route
135128
pub async fn update_email_notifications(app: AppState, req: BytesRequest) -> AppResult<Response> {
129+
use diesel::pg::upsert::excluded;
130+
use diesel_async::RunQueryDsl;
131+
136132
let (parts, body) = req.0.into_parts();
137133

138134
#[derive(Deserialize)]
@@ -152,51 +148,45 @@ pub async fn update_email_notifications(app: AppState, req: BytesRequest) -> App
152148
.check(&parts, &mut conn)
153149
.await?
154150
.user_id();
155-
spawn_blocking(move || {
156-
use diesel::RunQueryDsl;
157151

158-
let conn: &mut AsyncConnectionWrapper<_> = &mut conn.into();
159-
160-
use diesel::pg::upsert::excluded;
161-
162-
// Build inserts from existing crates belonging to the current user
163-
let to_insert = CrateOwner::by_owner_kind(OwnerKind::User)
164-
.filter(crate_owners::owner_id.eq(user_id))
165-
.select((
166-
crate_owners::crate_id,
167-
crate_owners::owner_id,
168-
crate_owners::owner_kind,
169-
crate_owners::email_notifications,
170-
))
171-
.load(conn)?
172-
.into_iter()
173-
// Remove records whose `email_notifications` will not change from their current value
174-
.map(
175-
|(c_id, o_id, o_kind, e_notifications): (i32, i32, i32, bool)| {
176-
let current_e_notifications = *updates.get(&c_id).unwrap_or(&e_notifications);
177-
(
178-
crate_owners::crate_id.eq(c_id),
179-
crate_owners::owner_id.eq(o_id),
180-
crate_owners::owner_kind.eq(o_kind),
181-
crate_owners::email_notifications.eq(current_e_notifications),
182-
)
183-
},
184-
)
185-
.collect::<Vec<_>>();
186-
187-
// Upsert crate owners; this should only actually execute updates
188-
diesel::insert_into(crate_owners::table)
189-
.values(&to_insert)
190-
.on_conflict((
191-
crate_owners::crate_id,
192-
crate_owners::owner_id,
193-
crate_owners::owner_kind,
194-
))
195-
.do_update()
196-
.set(crate_owners::email_notifications.eq(excluded(crate_owners::email_notifications)))
197-
.execute(conn)?;
198-
199-
ok_true()
200-
})
201-
.await
152+
// Build inserts from existing crates belonging to the current user
153+
let to_insert = CrateOwner::by_owner_kind(OwnerKind::User)
154+
.filter(crate_owners::owner_id.eq(user_id))
155+
.select((
156+
crate_owners::crate_id,
157+
crate_owners::owner_id,
158+
crate_owners::owner_kind,
159+
crate_owners::email_notifications,
160+
))
161+
.load(&mut conn)
162+
.await?
163+
.into_iter()
164+
// Remove records whose `email_notifications` will not change from their current value
165+
.map(
166+
|(c_id, o_id, o_kind, e_notifications): (i32, i32, i32, bool)| {
167+
let current_e_notifications = *updates.get(&c_id).unwrap_or(&e_notifications);
168+
(
169+
crate_owners::crate_id.eq(c_id),
170+
crate_owners::owner_id.eq(o_id),
171+
crate_owners::owner_kind.eq(o_kind),
172+
crate_owners::email_notifications.eq(current_e_notifications),
173+
)
174+
},
175+
)
176+
.collect::<Vec<_>>();
177+
178+
// Upsert crate owners; this should only actually execute updates
179+
diesel::insert_into(crate_owners::table)
180+
.values(&to_insert)
181+
.on_conflict((
182+
crate_owners::crate_id,
183+
crate_owners::owner_id,
184+
crate_owners::owner_kind,
185+
))
186+
.do_update()
187+
.set(crate_owners::email_notifications.eq(excluded(crate_owners::email_notifications)))
188+
.execute(&mut conn)
189+
.await?;
190+
191+
ok_true()
202192
}

0 commit comments

Comments
 (0)