Skip to content

Commit 80d6ed4

Browse files
authored
Merge pull request #9936 from Turbo87/async-categories
boot/categories: Migrate `sync_with_connection()` to `diesel-async` queries
2 parents f63b493 + db2f11c commit 80d6ed4

File tree

3 files changed

+71
-53
lines changed

3 files changed

+71
-53
lines changed

src/bin/crates-admin/migrate.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,19 @@ pub async fn run(_opts: Opts) -> Result<(), Error> {
4545

4646
let mut conn = AsyncConnectionWrapper::<AsyncPgConnection>::from(conn);
4747

48-
spawn_blocking(move || {
49-
info!("Migrating the database");
48+
info!("Migrating the database");
49+
let mut conn = spawn_blocking(move || {
5050
HarnessWithOutput::write_to_stdout(&mut conn)
5151
.run_pending_migrations(MIGRATIONS)
5252
.map_err(|e| anyhow!(e))
5353
.context("Failed to run migrations")?;
5454

55-
info!("Synchronizing crate categories");
56-
crates_io::boot::categories::sync_with_connection(CATEGORIES_TOML, &mut conn)?;
57-
58-
Ok(())
55+
Ok::<_, Error>(conn)
5956
})
60-
.await
57+
.await?;
58+
59+
info!("Synchronizing crate categories");
60+
crates_io::boot::categories::sync_with_connection(CATEGORIES_TOML, &mut conn).await?;
61+
62+
Ok(())
6163
}

src/boot/categories.rs

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// Sync available crate categories from `src/categories.toml`.
22
// Runs when the server is started.
33

4-
use crate::util::diesel::prelude::*;
5-
use crate::util::diesel::Conn;
64
use anyhow::{Context, Result};
5+
use crates_io_database::schema::categories;
6+
use diesel::pg::upsert::excluded;
7+
use diesel::prelude::*;
8+
use diesel_async::scoped_futures::ScopedFutureExt;
9+
use diesel_async::{AsyncConnection, AsyncPgConnection, RunQueryDsl};
710

811
#[derive(Debug)]
912
struct Category {
@@ -76,11 +79,7 @@ fn categories_from_toml(
7679
Ok(result)
7780
}
7881

79-
pub fn sync_with_connection(toml_str: &str, conn: &mut impl Conn) -> Result<()> {
80-
use crate::schema::categories;
81-
use diesel::pg::upsert::excluded;
82-
use diesel::RunQueryDsl;
83-
82+
pub async fn sync_with_connection(toml_str: &str, conn: &mut AsyncPgConnection) -> Result<()> {
8483
let toml: toml::value::Table =
8584
toml::from_str(toml_str).context("Could not parse categories toml")?;
8685

@@ -97,20 +96,27 @@ pub fn sync_with_connection(toml_str: &str, conn: &mut impl Conn) -> Result<()>
9796
.collect::<Vec<_>>();
9897

9998
conn.transaction(|conn| {
100-
let slugs: Vec<String> = diesel::insert_into(categories::table)
101-
.values(&to_insert)
102-
.on_conflict(categories::slug)
103-
.do_update()
104-
.set((
105-
categories::category.eq(excluded(categories::category)),
106-
categories::description.eq(excluded(categories::description)),
107-
))
108-
.returning(categories::slug)
109-
.get_results(conn)?;
110-
111-
diesel::delete(categories::table)
112-
.filter(categories::slug.ne_all(slugs))
113-
.execute(conn)?;
114-
Ok(())
99+
async move {
100+
let slugs: Vec<String> = diesel::insert_into(categories::table)
101+
.values(&to_insert)
102+
.on_conflict(categories::slug)
103+
.do_update()
104+
.set((
105+
categories::category.eq(excluded(categories::category)),
106+
categories::description.eq(excluded(categories::description)),
107+
))
108+
.returning(categories::slug)
109+
.get_results(conn)
110+
.await?;
111+
112+
diesel::delete(categories::table)
113+
.filter(categories::slug.ne_all(slugs))
114+
.execute(conn)
115+
.await?;
116+
117+
Ok(())
118+
}
119+
.scope_boxed()
115120
})
121+
.await
116122
}

src/tests/categories.rs

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::schema::categories;
22
use crates_io_test_db::TestDatabase;
33
use diesel::*;
4+
use diesel_async::{AsyncConnection, AsyncPgConnection, RunQueryDsl};
45

56
const ALGORITHMS: &str = r#"
67
[algorithms]
@@ -37,56 +38,65 @@ name = "Another"
3738
description = "Another category ho hum"
3839
"#;
3940

40-
fn select_slugs(conn: &mut PgConnection) -> Vec<String> {
41+
async fn select_slugs(conn: &mut AsyncPgConnection) -> Vec<String> {
4142
categories::table
4243
.select(categories::slug)
4344
.order(categories::slug)
4445
.load(conn)
46+
.await
4547
.unwrap()
4648
}
4749

48-
#[test]
49-
fn sync_adds_new_categories() {
50+
#[tokio::test]
51+
async fn sync_adds_new_categories() {
5052
let test_db = TestDatabase::new();
51-
let mut conn = test_db.connect();
53+
let mut conn = AsyncPgConnection::establish(test_db.url()).await.unwrap();
5254

53-
crate::boot::categories::sync_with_connection(ALGORITHMS_AND_SUCH, &mut conn).unwrap();
55+
crate::boot::categories::sync_with_connection(ALGORITHMS_AND_SUCH, &mut conn)
56+
.await
57+
.unwrap();
5458

55-
let categories = select_slugs(&mut conn);
59+
let categories = select_slugs(&mut conn).await;
5660
assert_eq!(categories, vec!["algorithms", "algorithms::such"]);
5761
}
5862

59-
#[test]
60-
fn sync_removes_missing_categories() {
63+
#[tokio::test]
64+
async fn sync_removes_missing_categories() {
6165
let test_db = TestDatabase::new();
62-
let mut conn = test_db.connect();
66+
let mut conn = AsyncPgConnection::establish(test_db.url()).await.unwrap();
6367

64-
crate::boot::categories::sync_with_connection(ALGORITHMS_AND_SUCH, &mut conn).unwrap();
65-
crate::boot::categories::sync_with_connection(ALGORITHMS, &mut conn).unwrap();
68+
crate::boot::categories::sync_with_connection(ALGORITHMS_AND_SUCH, &mut conn)
69+
.await
70+
.unwrap();
71+
crate::boot::categories::sync_with_connection(ALGORITHMS, &mut conn)
72+
.await
73+
.unwrap();
6674

67-
let categories = select_slugs(&mut conn);
75+
let categories = select_slugs(&mut conn).await;
6876
assert_eq!(categories, vec!["algorithms"]);
6977
}
7078

71-
#[test]
72-
fn sync_adds_and_removes() {
79+
#[tokio::test]
80+
async fn sync_adds_and_removes() {
7381
let test_db = TestDatabase::new();
74-
let mut conn = test_db.connect();
82+
let mut conn = AsyncPgConnection::establish(test_db.url()).await.unwrap();
7583

76-
crate::boot::categories::sync_with_connection(ALGORITHMS_AND_SUCH, &mut conn).unwrap();
77-
crate::boot::categories::sync_with_connection(ALGORITHMS_AND_ANOTHER, &mut conn).unwrap();
84+
crate::boot::categories::sync_with_connection(ALGORITHMS_AND_SUCH, &mut conn)
85+
.await
86+
.unwrap();
87+
crate::boot::categories::sync_with_connection(ALGORITHMS_AND_ANOTHER, &mut conn)
88+
.await
89+
.unwrap();
7890

79-
let categories = select_slugs(&mut conn);
91+
let categories = select_slugs(&mut conn).await;
8092
assert_eq!(categories, vec!["algorithms", "another"]);
8193
}
8294

83-
#[test]
84-
fn test_real_categories() {
95+
#[tokio::test]
96+
async fn test_real_categories() {
8597
let test_db = TestDatabase::new();
86-
let mut conn = test_db.connect();
98+
let mut conn = AsyncPgConnection::establish(test_db.url()).await.unwrap();
8799

88100
const TOML: &str = include_str!("../boot/categories.toml");
89-
assert_ok!(crate::boot::categories::sync_with_connection(
90-
TOML, &mut conn
91-
));
101+
assert_ok!(crate::boot::categories::sync_with_connection(TOML, &mut conn).await);
92102
}

0 commit comments

Comments
 (0)