Events refinements: 'restored' flag on entity draft change, don't emit collection change when draft entity deleted.#593
Conversation
…es changed event Fixes a bug with duplicate events being emitted for collection changes. Co-Authored-By: Claude <noreply@anthropic.com>
…ake) Co-Authored-By: Claude <noreply@anthropic.com>
… soft deletes Co-Authored-By: Claude <noreply@anthropic.com>
|
Thanks for the pull request, @bradenmacdonald! This repository is currently maintained by Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review. 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. DetailsWhere can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources: When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
|
@ormsbee @kdmccormick Could I get your opinion here? When we delete a [draft] component or container, do you think openedx-core should: (A) send both the regular
or (B) send only the regular
The docs at https://github.com/openedx/openedx-core/blob/main/src/openedx_content/applets/collections/models.py don't say either way. Though collections could have been implemented as foreignkeys to the |
|
I would say (B). My concern with (A) is precisely what you lay out:
Collections are also used as a way for people authoring Courses to find library content to add to them. When they are doing so, they need to be viewing the published state of those items. Something with a deleted draft (where that deletion has not yet been published) should still show up in that Collection when it's being browsed from the "add to course" UI. |
I'm not sure this is working well at the moment. Some of the search index code conflates "draft doesn't exist" with "entity doesn't exist". But that's just a bug we can fix in the future, and I agree in principle, so I'll move forward with (B). |
This PR improves events in openedx-core.
It does these two things that I think we definitely want:
ENTITIES_DRAFT_CHANGEDevent, to add arestoredboolean field. This allows event handlers to distinguish between "newly created" draft entities and "un-deleted" draft entities, which was previously not possible with only the information in the event itself. This is a change to the event data payload, but it's adding a field and the event is brand new and not yet published/used anywhere. I think we do want this, although it does add an extra query to the event generation code.And it does this thing that I'm a bit on the fence about:
COLLECTIONS_CHANGEDevent to be less "smart", and not emit a "collection changed" event when an entity in the collection is deleted. This is a change to the event semantics.Background for the third change:
I tried to make the
COLLECTIONS_CHANGEDevent "smart" so that it would reflect any user-visible changes to collections. Specifically, if you soft-deleted an entity that was in a collection, you'd get aCOLLECTIONS_CHANGEDevent withentities_removed=[...]telling you that that entity is no longer in the collection. And if you then un-deleted that entity, you'd get aCOLLECTIONS_CHANGEDevent withentities_added=[...]showing that the entity was "re-added" to the collection when it was un-deleted.BUT this was fundamentally problematic because collections very deliberately are not part of the draft-publish workflow, and they technically shouldn't care about the "draft" state of an entity in particular. When testing the modulestore migrator in openedx-platform, I noticed that the related code was emitting redundant
COLLECTIONS_CHANGEDevents, because of this mismatch.The problem was with code like this:
When the bulk draft context ends, the
emit_collections_changed_for_entity_changes_taskwould look for "un-deleted" entities that are part of a collection, and emit "added to collection" events for them, but if you created them in this way, there would be duplicate events - one queued byadd_to_collection, and one queued when the bulk draft changes context ends.Now, it was possible to work around this using 7903aec to distinguish between "un-deleted" and "created" entities, and this mostly solved the bug, but there was still at least one major edge case:
In this case, the handler that runs when the bulk context ends ("look for un-deleted entities and emit 'added to collection' events for any collections they're part of") has no way to "know" that the
add_to_collectionAPI already emitted events for adding those entities to the collection.As far as I can tell, there is no clean way to update our code to avoid duplicate events in this case, while still emitting these "smart" events that reflect the draft state of the entities in the collection. Now, this isn't a huge deal as the duplicate events are only in a very particular edge case involving "un-deleting" entities, but the fact that we cannot really avoid this without some ugly hacks tells me that the event design needs to be improved. Which is why I'm suggesting this particular improvement now, because it's technically a breaking change to the semantics of the brand-new
COLLECTION_CHANGEDevent, and I want to "get it right" in our first release if possible, to avoid difficult changes later.What this PR changes:
COLLECTION_CHANGEDis no longer emitted when entities are soft-deleted or un-deleted, potentially affecting the contents of a collection. Instead, code that cares about this needs to also listen forENTITIES_DRAFT_CHANGEDevents indicating drafts are deleted or un-deleted.