From 8e39d24cded47b44c93e8f7919d25dc30466b978 Mon Sep 17 00:00:00 2001 From: akarras Date: Sun, 17 Sep 2023 22:21:06 -0600 Subject: [PATCH] fix: update db calls to not use dates in pks & reduce dupe key failures. closes #18 --- migration/src/lib.rs | 2 + ...0918_033709_remove_junk_pk_from_listing.rs | 55 +++++++++++++++++++ ultros-db/src/entity/active_listing.rs | 1 - .../entity/ffxiv_character_verification.rs | 2 +- ultros-db/src/entity/retainer.rs | 21 +++---- ultros-db/src/entity/world.rs | 19 ++++--- ultros-db/src/listings.rs | 9 +-- ultros-db/src/recently_updated.rs | 8 ++- ultros-db/src/sales.rs | 13 ++++- 9 files changed, 102 insertions(+), 28 deletions(-) create mode 100644 migration/src/m20230918_033709_remove_junk_pk_from_listing.rs diff --git a/migration/src/lib.rs b/migration/src/lib.rs index 967a5e50..a2a5a136 100644 --- a/migration/src/lib.rs +++ b/migration/src/lib.rs @@ -19,6 +19,7 @@ mod m20221112_211028_add_final_fantasy_character_relation_to_verification; mod m20221227_164853_price_alert; mod m20230311_230232_cleanup_fks; mod m20230312_184157_add_last_updated_table; +mod m20230918_033709_remove_junk_pk_from_listing; pub struct Migrator; @@ -47,6 +48,7 @@ impl MigratorTrait for Migrator { Box::new(m20221227_164853_price_alert::Migration), Box::new(m20230311_230232_cleanup_fks::Migration), Box::new(m20230312_184157_add_last_updated_table::Migration), + Box::new(m20230918_033709_remove_junk_pk_from_listing::Migration), ] } } diff --git a/migration/src/m20230918_033709_remove_junk_pk_from_listing.rs b/migration/src/m20230918_033709_remove_junk_pk_from_listing.rs new file mode 100644 index 00000000..d3fa7f68 --- /dev/null +++ b/migration/src/m20230918_033709_remove_junk_pk_from_listing.rs @@ -0,0 +1,55 @@ +use sea_orm_migration::prelude::*; + +use crate::m20220101_000001_create_table::{ActiveListing, SaleHistory}; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + // alter table sale_history + // drop constraint sale_history_pkey; + + // alter table sale_history + // add primary key (id); + manager + .drop_foreign_key( + ForeignKeyDropStatement::new() + .table(SaleHistory::Table) + .name("sale_history_pkey") + .to_owned(), + ) + .await?; + manager + .alter_table( + TableAlterStatement::new() + .modify_column(ColumnDef::new(SaleHistory::Id).primary_key()) + .table(SaleHistory::Table) + .to_owned(), + ) + .await?; + manager + .drop_foreign_key( + ForeignKeyDropStatement::new() + .table(ActiveListing::Table) + .name("active_listing_pkey") + .to_owned(), + ) + .await?; + manager + .alter_table( + TableAlterStatement::new() + .modify_column(ColumnDef::new(ActiveListing::Id).primary_key()) + .table(ActiveListing::Table) + .to_owned(), + ) + .await?; + Ok(()) + } + + async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> { + // Replace the sample below with your own migration scripts + todo!(); + } +} diff --git a/ultros-db/src/entity/active_listing.rs b/ultros-db/src/entity/active_listing.rs index ef5f6795..5eb7bda5 100644 --- a/ultros-db/src/entity/active_listing.rs +++ b/ultros-db/src/entity/active_listing.rs @@ -14,7 +14,6 @@ pub struct Model { pub price_per_unit: i32, pub quantity: i32, pub hq: bool, - #[sea_orm(primary_key, auto_increment = false)] pub timestamp: DateTime, } diff --git a/ultros-db/src/entity/ffxiv_character_verification.rs b/ultros-db/src/entity/ffxiv_character_verification.rs index 2621940b..ebbbe192 100644 --- a/ultros-db/src/entity/ffxiv_character_verification.rs +++ b/ultros-db/src/entity/ffxiv_character_verification.rs @@ -10,7 +10,7 @@ pub struct Model { pub discord_user_id: i64, pub ffxiv_character_id: i32, pub challenge: String, - #[sea_orm(primary_key)] + #[sea_orm(primary_key, auto_increment = false)] pub id: i32, } diff --git a/ultros-db/src/entity/retainer.rs b/ultros-db/src/entity/retainer.rs index bb2b3c4b..165cfa02 100644 --- a/ultros-db/src/entity/retainer.rs +++ b/ultros-db/src/entity/retainer.rs @@ -15,10 +15,10 @@ pub struct Model { #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { + #[sea_orm(has_many = "super::active_listing::Entity")] + ActiveListing, #[sea_orm(has_many = "super::owned_retainers::Entity")] OwnedRetainers, - #[sea_orm(has_many = "super::active_listing::Entity")] - ActiveListings, #[sea_orm( belongs_to = "super::retainer_city::Entity", from = "Column::RetainerCityId", @@ -37,6 +37,12 @@ pub enum Relation { World, } +impl Related for Entity { + fn to() -> RelationDef { + Relation::ActiveListing.def() + } +} + impl Related for Entity { fn to() -> RelationDef { Relation::OwnedRetainers.def() @@ -51,16 +57,7 @@ impl Related for Entity { impl Related for Entity { fn to() -> RelationDef { - super::active_listing::Relation::World.def() - } - fn via() -> Option { - Some(super::active_listing::Relation::Retainer.def().rev()) - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::ActiveListings.def() + Relation::World.def() } } diff --git a/ultros-db/src/entity/world.rs b/ultros-db/src/entity/world.rs index 785b657d..4b388330 100644 --- a/ultros-db/src/entity/world.rs +++ b/ultros-db/src/entity/world.rs @@ -15,6 +15,8 @@ pub struct Model { #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { + #[sea_orm(has_many = "super::active_listing::Entity")] + ActiveListing, #[sea_orm( belongs_to = "super::datacenter::Entity", from = "Column::DatacenterId", @@ -33,6 +35,12 @@ pub enum Relation { SaleHistory, } +impl Related for Entity { + fn to() -> RelationDef { + Relation::ActiveListing.def() + } +} + impl Related for Entity { fn to() -> RelationDef { Relation::Datacenter.def() @@ -51,18 +59,15 @@ impl Related for Entity { } } -impl Related for Entity { +impl Related for Entity { fn to() -> RelationDef { - Relation::SaleHistory.def() + Relation::Retainer.def() } } -impl Related for Entity { +impl Related for Entity { fn to() -> RelationDef { - super::active_listing::Relation::Retainer.def() - } - fn via() -> Option { - Some(super::active_listing::Relation::World.def().rev()) + Relation::SaleHistory.def() } } diff --git a/ultros-db/src/listings.rs b/ultros-db/src/listings.rs index 5ab22493..b7a5aad3 100644 --- a/ultros-db/src/listings.rs +++ b/ultros-db/src/listings.rs @@ -83,7 +83,7 @@ impl UltrosDb { _ => None, }) .map(|listing| async move { - active_listing::Entity::delete_by_id((listing.id, listing.timestamp)) + active_listing::Entity::delete_by_id(listing.id) .exec(&self.db) .await .map(|_| listing) @@ -292,9 +292,10 @@ impl UltrosDb { }); let (added, _removed_result) = futures::future::join(futures::future::join_all(added), async move { - let remove_result = futures::future::try_join_all(remove_iter.map(|(l, _)| { - active_listing::Entity::delete_by_id((l.id, l.timestamp)).exec(&self.db) - })) + let remove_result = futures::future::try_join_all( + remove_iter + .map(|(l, _)| active_listing::Entity::delete_by_id(l.id).exec(&self.db)), + ) .await?; Result::::Ok(remove_result.len()) }) diff --git a/ultros-db/src/recently_updated.rs b/ultros-db/src/recently_updated.rs index 2896e76f..04df7019 100644 --- a/ultros-db/src/recently_updated.rs +++ b/ultros-db/src/recently_updated.rs @@ -22,7 +22,13 @@ impl UltrosDb { match updated { Ok(_updated) => {} Err(_e) => { - model.insert(&self.db).await?; + match model.clone().insert(&self.db).await { + Ok(ok) => {} + Err(e) => { + // ok now can we update? + model.clone().update(&self.db).await?; + } + } } } Ok(()) diff --git a/ultros-db/src/sales.rs b/ultros-db/src/sales.rs index 4688b90a..45202c11 100644 --- a/ultros-db/src/sales.rs +++ b/ultros-db/src/sales.rs @@ -134,12 +134,21 @@ impl UltrosDb { let buyer = match buyer { Some(buyer) => buyer, None => { - unknown_final_fantasy_character::ActiveModel { + let result = unknown_final_fantasy_character::ActiveModel { name: ActiveValue::Set(name.to_string()), ..Default::default() } .insert(&self.db) - .await? + .await; + match result { + Ok(m) => m, + // the most common error here is a duplicate key, in this case we can just look them up now. + Err(e) => unknown_final_fantasy_character::Entity::find() + .filter(unknown_final_fantasy_character::Column::Name.eq(name)) + .one(&self.db) + .await? + .ok_or(e)?, + } } }; Ok::<_, anyhow::Error>((buyer.name.clone(), buyer))