-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
system combinators short circuiting with system failure #20671
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
system combinators short circuiting with system failure #20671
Conversation
|
It looks like your PR is a breaking change, but you didn't provide a migration guide. Please review the instructions for writing migration guides, then expand or revise the content in the migration guides directory to reflect your changes. |
| } | ||
|
|
||
| #[test] | ||
| fn run_fallible_condition() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test needs a clearer name.
| b: impl FnOnce(SystemIn<'_, A>) -> Result<B::Out, RunSystemError>, | ||
| ) -> Result<Self::Out, RunSystemError> { | ||
| Ok(!(a(input)? || b(input)?)) | ||
| <OrMarker as Combine<A, B>>::combine(input, a, b).map(|result| !result) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why this change, or the sibling change below, was required for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO the change from a simple a(input)? || b(input)? to the match cases makes the logic of the combinators less clear and not as understandable at a glance, and I figured it was easier to reason about by reusing the OrMarker code here.
I guess it's an aesthetic choice in the end though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit of an aesthetic choice, but more importantly, it's important to avoid mixing in unrelated / quasi-related changes to make understanding git history and review easier.
Can you please revert these here? I'd be happy to review them in a seperate PR (although my gut reaction is that this is less clear).
alice-i-cecile
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with this change in principle, but:
- This needs migration guides.
- The existing integration-y test would really benefit from improved clarity, either via comments or simplification.
- All of the combinators need to be tested for this behavior in some way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've never done a migration guide before so I just looked at the help and other guides but I'm not sure if this is correct
|
|
||
| #[test] | ||
| fn combinators_with_maybe_failing_condition() { | ||
| #![allow( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is specifically because I wanted the expected closure to exactly mirror the combinator systems. could do without allowing these but I think it would be less clear what's being tested against.
…tch_update could fail (and will under miri)
a9a8b1e to
008eab7
Compare
|
I agree that we should treat That could lead to a simpler implementation. If we define a conversion method like fn skipped_as_false(result: Result<bool, RunSystemError>) -> Result<bool, RunSystemError> {
match result {
Err(RunSystemError::Skipped(_)) => Ok(false),
result => result,
}
}then we could write all the combinators like |
|
Hmm. This is well implemented, and I think that the semantics are simpler with the current implementation. I'm neutral on the current design vs @chescock's proposal above on the whole. |
chescock
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree this is well-implemented! I'd still recommend the alternate semantics I proposed above, since I think errors should be reported as early as possible, but if @alice-i-cecile is happy with this behavior then I'm happy to approve this implementation!
|
I think that in practice this behavior is going to be more useful to users: skipping a system if a missing resource exists and another reason to skip the system is already in place will allow us to be more permissive about unusual gameplay states that have no observable impact on the actual running of the game. This in turn will avoid us proliferating run conditions, or forcing users to spam That said, I suppose there's an argument to be made for "just set your error handler to log a warning"? @janis-bhm, I value your opinion here, so I'll wait for you to have a chance to respond before we merge this. |
Just to be clear: I wasn't proposing asking users to call that method! It would be a non- I'll also note that either formulation means we can use My background may be giving me the wrong instincts here. I've mostly worked on business applications where we want to abort on errors before they can spread, but a game engine will usually want to keep running and hope something fun happens. I'd still vote for "just set your error handler to log a warning", since then you can at least see that something unexpected happened. |
|
While |
Ah, I totally missed this. @janis-bhm, let us know when you have changes for us to consider :) |
|
@alice-i-cecile I'm not totally happy with this because it moves the error handling away from the executor and into the combinator system, but this makes the combinators implementations easy to read again, and in the case where both systems return an error, I think this is the simplest way to let them both be sent to the world's error handler. |
Objective
Fixes #20376:
CombinatorSystems short circuit if one of the systems fails to validate, e.g. because it queries a Component that isn't resident in the world.
Solution
Instead, we can treat the system failing as the system yielding
false, appropriately querying the second system depending on the logical operator.Testing
I added a new test that calls the combinators in different configurations with a failing system as both the rhs and lhs of the combinator and counts the invocations of the system and the condition.