From 2d5d2d5df842ddfba62a61c62105c104e5f7d17c Mon Sep 17 00:00:00 2001 From: Josiah Glosson Date: Tue, 6 May 2025 10:06:46 -0500 Subject: [PATCH] Fix to attached world data (#3618) * Add AttachedWorldData::remove_for_world * Box the S3 error for daedelus_client ErrorKind::S3 * Delete attached world data on world deletion --- .../ui/world/modal/EditServerModal.vue | 2 +- apps/daedalus_client/src/error.rs | 2 +- apps/daedalus_client/src/util.rs | 2 +- ...cf9a4fc5a9817f4831c66bd56f2f4d0a00f82.json | 12 ++++++ .../app-lib/src/state/attached_world_data.rs | 23 +++++++++++ packages/app-lib/src/state/fs_watcher.rs | 41 ++++++++++++++----- 6 files changed, 68 insertions(+), 14 deletions(-) create mode 100644 packages/app-lib/.sqlx/query-1a979fbc58be7dde562b6f7c8fdcf9a4fc5a9817f4831c66bd56f2f4d0a00f82.json diff --git a/apps/app-frontend/src/components/ui/world/modal/EditServerModal.vue b/apps/app-frontend/src/components/ui/world/modal/EditServerModal.vue index 626d5f2fc..5e03bbb89 100644 --- a/apps/app-frontend/src/components/ui/world/modal/EditServerModal.vue +++ b/apps/app-frontend/src/components/ui/world/modal/EditServerModal.vue @@ -54,7 +54,7 @@ async function saveServer() { 'server', address.value, newDisplayStatus.value, - ) + ).catch(handleError) } emit('submit', { diff --git a/apps/daedalus_client/src/error.rs b/apps/daedalus_client/src/error.rs index d4a0167cb..37992a142 100644 --- a/apps/daedalus_client/src/error.rs +++ b/apps/daedalus_client/src/error.rs @@ -22,7 +22,7 @@ pub enum ErrorKind { Fetch { inner: reqwest::Error, item: String }, #[error("Error while uploading file to S3: {file}")] S3 { - inner: s3::error::S3Error, + inner: Box, file: String, }, #[error("Error acquiring semaphore: {0}")] diff --git a/apps/daedalus_client/src/util.rs b/apps/daedalus_client/src/util.rs index b5e4b360a..62b2b9ca5 100644 --- a/apps/daedalus_client/src/util.rs +++ b/apps/daedalus_client/src/util.rs @@ -78,7 +78,7 @@ pub async fn upload_file_to_bucket( BUCKET.put_object(key.clone(), &bytes).await } .map_err(|err| ErrorKind::S3 { - inner: err, + inner: Box::new(err), file: path.clone(), }); diff --git a/packages/app-lib/.sqlx/query-1a979fbc58be7dde562b6f7c8fdcf9a4fc5a9817f4831c66bd56f2f4d0a00f82.json b/packages/app-lib/.sqlx/query-1a979fbc58be7dde562b6f7c8fdcf9a4fc5a9817f4831c66bd56f2f4d0a00f82.json new file mode 100644 index 000000000..01e5e90d4 --- /dev/null +++ b/packages/app-lib/.sqlx/query-1a979fbc58be7dde562b6f7c8fdcf9a4fc5a9817f4831c66bd56f2f4d0a00f82.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n DELETE FROM attached_world_data\n WHERE profile_path = $1 and world_type = $2 and world_id = $3\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "1a979fbc58be7dde562b6f7c8fdcf9a4fc5a9817f4831c66bd56f2f4d0a00f82" +} diff --git a/packages/app-lib/src/state/attached_world_data.rs b/packages/app-lib/src/state/attached_world_data.rs index 17b8b4ace..9d161799d 100644 --- a/packages/app-lib/src/state/attached_world_data.rs +++ b/packages/app-lib/src/state/attached_world_data.rs @@ -62,6 +62,29 @@ impl AttachedWorldData { }) .collect()) } + + pub async fn remove_for_world( + instance: &str, + world_type: WorldType, + world_id: &str, + exec: impl sqlx::Executor<'_, Database = sqlx::Sqlite>, + ) -> crate::Result<()> { + let world_type = world_type.as_str(); + + sqlx::query!( + " + DELETE FROM attached_world_data + WHERE profile_path = $1 and world_type = $2 and world_id = $3 + ", + instance, + world_type, + world_id + ) + .execute(exec) + .await?; + + Ok(()) + } } macro_rules! attached_data_setter { diff --git a/packages/app-lib/src/state/fs_watcher.rs b/packages/app-lib/src/state/fs_watcher.rs index d2a2ed2d8..347a7a38e 100644 --- a/packages/app-lib/src/state/fs_watcher.rs +++ b/packages/app-lib/src/state/fs_watcher.rs @@ -1,6 +1,10 @@ +use crate::State; use crate::event::ProfilePayloadType; use crate::event::emit::{emit_profile, emit_warning}; -use crate::state::{DirectoryInfo, ProfileInstallStage, ProjectType}; +use crate::state::{ + DirectoryInfo, ProfileInstallStage, ProjectType, attached_world_data, +}; +use crate::worlds::WorldType; use futures::{SinkExt, StreamExt, channel::mpsc::channel}; use notify::{RecommendedWatcher, RecursiveMode}; use notify_debouncer_mini::{DebounceEventResult, Debouncer, new_debouncer}; @@ -87,16 +91,31 @@ pub async fn init_watcher() -> crate::Result { "World updated: {}", e.path.display() ); - Some(ProfilePayloadType::WorldUpdated { - world: e - .path - .parent() - .unwrap() - .file_name() - .unwrap() - .to_string_lossy() - .to_string(), - }) + let world = e + .path + .parent() + .unwrap() + .file_name() + .unwrap() + .to_string_lossy() + .to_string(); + if !e.path.is_file() { + let profile_path_str = profile_path_str.clone(); + let world = world.clone(); + tokio::spawn(async move { + if let Ok(state) = State::get().await { + if let Err(e) = attached_world_data::AttachedWorldData::remove_for_world( + &profile_path_str, + WorldType::Singleplayer, + &world, + &state.pool + ).await { + tracing::warn!("Failed to remove AttachedWorldData for '{world}': {e}") + } + } + }); + } + Some(ProfilePayloadType::WorldUpdated { world }) } else if first_file_name .filter(|x| *x == "saves") .is_none()