Remove the document from Meilisearch when an entity is deleted#156
Open
loevgaard wants to merge 1 commit into
Open
Remove the document from Meilisearch when an entity is deleted#156loevgaard wants to merge 1 commit into
loevgaard wants to merge 1 commit into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #156 +/- ##
============================================
+ Coverage 43.86% 45.17% +1.31%
- Complexity 729 734 +5
============================================
Files 131 131
Lines 2387 2406 +19
============================================
+ Hits 1047 1087 +40
+ Misses 1340 1319 -21 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
loevgaard
commented
Jul 10, 2026
33bb045 to
eefffde
Compare
26b03ca to
5df71ee
Compare
RemoveEntity is dispatched from postRemove, after the row is already gone, but the handler reloaded the entity via find(), got null, and threw UnrecoverableMessageHandlingException. So async transports marked the message unrecoverable (orphaned documents) and the sync default failed the delete flush. - RemoveEntityHandler no longer reloads: it resolves the affected indexes via IndexRegistry::getByEntity() and removes the document by its id (the stringified entity id the message already carries). - Add removeByIds() directly to IndexerInterface (no separate capability interface — the plugin has no stable release, so BC isn't a concern). - removeByIds()/removeEntities() issue one batch deleteDocuments task per scope instead of one deleteDocument task per entity. - EntityListener::postRemove detaches the entity from the SplObjectStorage so it no longer leaks entries in long-running workers. Closes #111
5df71ee to
00d3831
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
Deleting an indexable entity never removed its document from Meilisearch, so deleted products stayed searchable forever.
RemoveEntityis dispatched frompostRemove— at that point the row is already deleted — but the handler then reloaded the entity viafind(), gotnull, and threwUnrecoverableMessageHandlingException. So on async transports the message was marked unrecoverable (orphaned documents accumulate), and on the sync default the exception propagated out of the delete flush and could fail the whole request.Changes:
RemoveEntityHandlerno longer reloads the entity. It resolves the affected indexes viaIndexRegistry::getByEntity($message->class)and removes the document by its id — the stringified entity id the message already carries (seeIndexableAwareTrait).IdRemovalCapableIndexerInterface::removeByIds(array $ids), implemented byDefaultIndexer, with aninstanceofcheck in the handler so custom indexers stay BC (they're skipped with a logged warning).removeByIds()(and the refactoredremoveEntities()) issue onedeleteDocumentstask per scope instead of onedeleteDocumentHTTP task per entity.EntityListener::postRemovenowdetach()es the entity from theSplObjectStorage, which was attach-only and grew unbounded in long-running workers.Testing
RemoveEntityHandlerTest: removes by id without reloading the entity (so it no longer throws in the sync setup); skips indexers that can't remove by id.DefaultIndexerTest::it_removes_documents_with_one_batch_delete_task_per_scope: a singledeleteDocuments([...])per scope.EntityListenerTest: afterpreRemove+postRemove, aRemoveEntityis dispatched and theSplObjectStorageretains no entries.Closes #111
Stacked on #155 (#128).