Prevent replace_related
from triggering lifecycle events
#20800
+41
−12
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Objective
EntityWorldMut::replace_related
triggersInsert
andReplace
lifecycle events of the target. Additionally, depending on the input, it will also triggerAdd
andRemove
. This happens when there is no intersection between the old and new relations because we start by removing the old before adding the new.Triggering
Add
andRemove
is clearly wrong. ForInsert
andReplace
there are two perspectives:replace_related
as mutating theRelationshipTarget
component in which case no lifecycle events should trigger;replace_related
as replacing theRelationshipTarget
component in which caseInsert
andReplace
should fire.This PR goes with the first approach because:
replace_related_with_difference
which doesn't fire any lifecycle events.Solution
Building on the existing trick, we populate the dummy with the entity id of the target, ensuring that the
RelationshipTarget
component never gets emptied during the breaking of existing relations. This preventsRemove
.Finally we restore the correctly initialized
RelationshipTarget
component by mutating it directly instead of usingEntityWorldMut::insert
to avoid triggeringInsert
andReplace
.Testing
Added a test to ensure this works correctly.
Added a similar test for
replace_related_with_difference
.