Skip to content

Commit 55cf2b1

Browse files
committed
prevent race conditions when initializing crate record in DB
1 parent 7485f33 commit 55cf2b1

File tree

1 file changed

+18
-36
lines changed

1 file changed

+18
-36
lines changed

src/db/add_package.rs

+18-36
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub(crate) async fn add_package_into_database(
4242
archive_storage: bool,
4343
) -> Result<i32> {
4444
debug!("Adding package into database");
45-
let crate_id = initialize_package_in_database(conn, metadata_pkg).await?;
45+
let crate_id = initialize_crate(conn, &metadata_pkg.name).await?;
4646
let dependencies = convert_dependencies(metadata_pkg);
4747
let rustdoc = get_rustdoc(metadata_pkg, source_dir).unwrap_or(None);
4848
let readme = get_readme(metadata_pkg, source_dir).unwrap_or(None);
@@ -261,24 +261,19 @@ pub(crate) async fn add_build_into_database(
261261
Ok(build_id)
262262
}
263263

264-
async fn initialize_package_in_database(
265-
conn: &mut sqlx::PgConnection,
266-
pkg: &MetadataPackage,
267-
) -> Result<i32> {
268-
if let Some(id) = sqlx::query_scalar!("SELECT id FROM crates WHERE name = $1", pkg.name)
269-
.fetch_optional(&mut *conn)
270-
.await?
271-
{
272-
Ok(id)
273-
} else {
274-
// insert crate into database if it is not exists
275-
Ok(sqlx::query_scalar!(
276-
"INSERT INTO crates (name) VALUES ($1) RETURNING id",
277-
pkg.name,
278-
)
279-
.fetch_one(&mut *conn)
280-
.await?)
281-
}
264+
pub(crate) async fn initialize_crate(conn: &mut sqlx::PgConnection, name: &str) -> Result<i32> {
265+
sqlx::query_scalar!(
266+
"INSERT INTO crates (name)
267+
VALUES ($1)
268+
ON CONFLICT (name) DO UPDATE
269+
SET -- this `SET` is needed so the id is always returned.
270+
name = EXCLUDED.name
271+
RETURNING id",
272+
name
273+
)
274+
.fetch_one(&mut *conn)
275+
.await
276+
.map_err(Into::into)
282277
}
283278

284279
/// Convert dependencies into Vec<(String, String, String, bool)>
@@ -526,7 +521,7 @@ where
526521
mod test {
527522
use super::*;
528523
use crate::test::*;
529-
use crate::utils::{CargoMetadata, MetadataPackage};
524+
use crate::utils::CargoMetadata;
530525
use test_case::test_case;
531526

532527
#[test]
@@ -647,13 +642,7 @@ mod test {
647642
async_wrapper(|env| async move {
648643
let mut conn = env.async_db().await.async_conn().await;
649644

650-
let crate_id = initialize_package_in_database(
651-
&mut conn,
652-
&MetadataPackage {
653-
..Default::default()
654-
},
655-
)
656-
.await?;
645+
let crate_id = initialize_crate(&mut conn, "").await?;
657646

658647
let owner1 = CrateOwner {
659648
avatar: "avatar".into(),
@@ -691,8 +680,7 @@ mod test {
691680
fn update_owner_detais() {
692681
async_wrapper(|env| async move {
693682
let mut conn = env.async_db().await.async_conn().await;
694-
let crate_id =
695-
initialize_package_in_database(&mut conn, &MetadataPackage::default()).await?;
683+
let crate_id = initialize_crate(&mut conn, "").await?;
696684

697685
// set initial owner details
698686
update_owners_in_database(
@@ -737,13 +725,7 @@ mod test {
737725
fn add_new_owners_and_delete_old() {
738726
async_wrapper(|env| async move {
739727
let mut conn = env.async_db().await.async_conn().await;
740-
let crate_id = initialize_package_in_database(
741-
&mut conn,
742-
&MetadataPackage {
743-
..Default::default()
744-
},
745-
)
746-
.await?;
728+
let crate_id = initialize_crate(&mut conn, "").await?;
747729

748730
// set initial owner details
749731
update_owners_in_database(

0 commit comments

Comments
 (0)