Skip to content

AssetServer LoadState API consistency #15237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

crvarner
Copy link
Contributor

Objective

Solution

  • implement consistently named LoadState accessor methods:
    • load_state, dependency_load_state, recursive_dependency_load_state (return unwrapped load states)
    • get_load_state, get_dependency_load_state, get_recursive_dependency_load_state (return Option)
    • is_loaded, is_loaded_with_dependencies, is_loaded_with_recursive_dependencies (return bool)
  • adds AssetLoadError to DependencyLoadState::Failed and RecursiveDependencyLoadState::Failed

Testing

  • Added coverage to existing unit tests

@crvarner crvarner force-pushed the issue15098-asset-server-is-loaded-with-deps-return branch 2 times, most recently from 2175185 to 6b17d95 Compare September 15, 2024 20:11
@alice-i-cecile alice-i-cecile added A-Assets Load files from disk to use for things like images, models, and sounds C-Usability A targeted quality-of-life change that makes Bevy easier to use M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide labels Sep 15, 2024
Copy link
Contributor

It looks like your PR is a breaking change, but you didn't provide a migration guide.

Could you add some context on what users should update when this change get released in a new version of Bevy?
It will be used to help writing the migration guide for the version. Putting it after a ## Migration Guide will help it get automatically picked up by our tooling.

@alice-i-cecile alice-i-cecile added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged D-Straightforward Simple bug fixes and API improvements, docs, test and examples labels Sep 15, 2024
@alice-i-cecile
Copy link
Member

What else needs to be done before this is ready for review?

@crvarner crvarner marked this pull request as ready for review September 15, 2024 20:20
@crvarner
Copy link
Contributor Author

I usually just wait for checks to pass first :)

@alice-i-cecile alice-i-cecile added S-Needs-Review Needs reviewer attention (from anyone!) to move forward and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Sep 15, 2024
@@ -506,7 +514,7 @@ impl AssetInfos {
if let Some(info) = self.get_mut(id) {
info.loading_dependencies.remove(&loaded_asset_id);
if info.loading_dependencies.is_empty() {
// send dependencies loaded event
// send dependencies loaded event (wouldn't this overwrite previous Failed state?)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems broken as is. Example: A depends on B and C.

  1. B fails to load.
  2. Line 624: B removed from A.loading_dependencies and
  3. Line 628: A.dep_load_state is set to Failed
  4. C successfully loads
  5. Line 515: C removed from A.loading_dependencies (now empty)
  6. Line 518: A.dep_load_state overwritten to Loaded

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a new unit test that confirmed the previous impl was overwriting previously failed dependencies. Added this check to fix it.

info.dep_load_state = DependencyLoadState::Loaded;
if !matches!(info.dep_load_state, DependencyLoadState::Failed(_)) {
// send dependencies loaded event
info.dep_load_state = DependencyLoadState::Loaded;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prior to this change, the added test dependency_load_states would fail due to a successful dependency load overwriting a previous failed dependency load.

@@ -450,7 +458,7 @@ impl AssetInfos {
RecursiveDependencyLoadState::Loaded
}
(_loading, 0) => RecursiveDependencyLoadState::Loading,
(_loading, _failed) => RecursiveDependencyLoadState::Failed,
(_loading, _failed) => RecursiveDependencyLoadState::Failed(rec_dep_error.unwrap()),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To preserve the previous behavior, I separated the errors based on where they were found. I'm not sure this makes sense though. In general, the interaction between DependencyLoadState and RecursiveDependencyLoadState is pretty confusing.

IMO we should simplify to just LoadState and DependencyLoadState (which are affected by their own dependencies recursively) unless there is a clear use case for distinguishing between deps and recursive deps.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree. Follow-up though :)

Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of cleanup items, but I'm on board with this. I'm generally in favor of the error-handling cleanup you've mentioned as well, but let's keep this PR scoped.

I think I would prefer a Vec of errors, but I'll defer to you on whether to do that in this PR or follow-up.

@crvarner
Copy link
Contributor Author

I think I would prefer a Vec of errors, but I'll defer to you on whether to do that in this PR or follow-up.

I also think a Vec would be better, but don’t see a super logical way to implement it without either the error handling cleanup going in first or a better understand of the interaction bwtween deps and rec_deps.

@alice-i-cecile
Copy link
Member

KK, let's get this merged first, then clean up the error handling, then move to a vec or hashmap of errors :)

- implements consistently named AssertServer methods for
    asset, dependency, and recursive dependency load states
- adds error to DependencyLoadState::Failed and
    RecursiveDependencyLoadState::Failed
- fixes bug where successful dependency load overwrites
    previous dependency failed load state
@crvarner crvarner force-pushed the issue15098-asset-server-is-loaded-with-deps-return branch from 28b5e84 to 260a7ae Compare September 16, 2024 18:13
@crvarner
Copy link
Contributor Author

cleanup items resolved :)

matches!(self.load_state(id), LoadState::Loaded)
}

/// Convenience method that returns true if the asset and all of its direct dependencies have been loaded.
pub fn is_loaded_with_dependencies(&self, id: impl Into<UntypedAssetId>) -> bool {
Copy link
Member

@janhohenheim janhohenheim Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I seeing it right that current calls to is_loaded_with_dependencies now has different semantics and that users should replace it with is_loaded_with_recursive_dependencies to keep their code working as before? If so, this seems like an incredibly silent footgun. Users upgrading their version without looking at the migration guides will have no idea that their code is now slightly wrong.
If my assessment is correct, we should ensure that this cannot happen, e.g. by leaving the semantics in place and introducing a is_loaded_with_direct_dependencies. I also don't like how the variant that you will usually want, namely is_loaded_with_recursive_dependencies, has a longer / more technical name than is_loaded_with_dependencies, which is probably not what you want.
But maybe I am misunderstanding the code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No misunderstanding, you are absolutely right. I will revert the name of is_loaded_with_recursive_dependencies to is_loaded_with_dependencies to preserve the original semantics. I will rename the check for self + direct deps to is_loaded_with_direct_dependencies

@janhohenheim janhohenheim removed the S-Needs-Review Needs reviewer attention (from anyone!) to move forward label Sep 19, 2024
@janhohenheim janhohenheim added the S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged label Sep 19, 2024
Copy link
Member

@janhohenheim janhohenheim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks! I think the breaking changes are minor and trivial enough that it's alright we're missing a migration guide.

@janhohenheim janhohenheim added C-Feature A new feature, making something new possible S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Sep 19, 2024
@crvarner
Copy link
Contributor Author

Part of me wants to rename the LoadState returning methods as well to be consistent, but I think that belongs in a follow up PR focused on this: #15237 (comment)

@alice-i-cecile alice-i-cecile added this pull request to the merge queue Sep 19, 2024
Merged via the queue into bevyengine:main with commit 612897b Sep 19, 2024
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Assets Load files from disk to use for things like images, models, and sounds C-Feature A new feature, making something new possible C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Straightforward Simple bug fixes and API improvements, docs, test and examples M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

AssetServer::is_loaded_with_dependencies should return a LoadState.
3 participants