From 0dfdd87248702fd691c7348d750565981e6d7807 Mon Sep 17 00:00:00 2001 From: Joseph <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 10 Jun 2024 05:56:21 -0700 Subject: [PATCH] Improve error handling for `AssetServer::add_async` (#13745) # Objective The method `AssetServer::add_async` (added in https://github.com/bevyengine/bevy/pull/13700) requires a future that returns an `AssetLoadError` error, which was a bit of an oversight on my part, as that type of error only really makes sense in the context of bevy's own asset loader -- returning it from user-defined futures isn't very useful. ## Solution Allow passing custom error types to `add_async`, which get cast into a trait object matching the form of `AssetLoader::load`. If merged before the next release this will not be a breaking change --- crates/bevy_asset/src/server/mod.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/crates/bevy_asset/src/server/mod.rs b/crates/bevy_asset/src/server/mod.rs index 46e334ec66079..a75fb9a4a4beb 100644 --- a/crates/bevy_asset/src/server/mod.rs +++ b/crates/bevy_asset/src/server/mod.rs @@ -718,9 +718,9 @@ impl AssetServer { /// /// After the asset has been fully loaded, it will show up in the relevant [`Assets`] storage. #[must_use = "not using the returned strong handle may result in the unexpected release of the asset"] - pub fn add_async( + pub fn add_async( &self, - future: impl Future> + Send + 'static, + future: impl Future> + Send + 'static, ) -> Handle { let handle = self .data @@ -741,12 +741,15 @@ impl AssetServer { .unwrap(); } Err(error) => { + let error = AddAsyncError { + error: Arc::new(error), + }; error!("{error}"); event_sender .send(InternalAssetEvent::Failed { id, path: Default::default(), - error, + error: AssetLoadError::AddAsyncError(error), }) .unwrap(); } @@ -1403,6 +1406,8 @@ pub enum AssetLoadError { CannotLoadIgnoredAsset { path: AssetPath<'static> }, #[error(transparent)] AssetLoaderError(#[from] AssetLoaderError), + #[error(transparent)] + AddAsyncError(#[from] AddAsyncError), #[error("The file at '{}' does not contain the labeled asset '{}'; it contains the following {} assets: {}", base_path, label, @@ -1441,6 +1446,22 @@ impl AssetLoaderError { } } +#[derive(Error, Debug, Clone)] +#[error("An error occurred while resolving an asset added by `add_async`: {error}")] +pub struct AddAsyncError { + error: Arc, +} + +impl PartialEq for AddAsyncError { + /// Equality comparison is not full (only through `TypeId`) + #[inline] + fn eq(&self, other: &Self) -> bool { + self.error.type_id() == other.error.type_id() + } +} + +impl Eq for AddAsyncError {} + /// An error that occurs when an [`AssetLoader`] is not registered for a given extension. #[derive(Error, Debug, Clone, PartialEq, Eq)] #[error("no `AssetLoader` found{}", format_missing_asset_ext(.extensions))]