Skip to content

Option to listen to postRemove event #96

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

Merged
merged 13 commits into from
Jul 1, 2021
Merged

Option to listen to postRemove event #96

merged 13 commits into from
Jul 1, 2021

Conversation

codedge
Copy link
Contributor

@codedge codedge commented Jun 21, 2021

This PR adds the option to listen to Doctrines postRemove. This is a result of the discussion in #62, a first step.

You can know specify in meili_search.yml:

meili_search:
    # One, or multiple of postPersist, postUpdate, preRemove, postRemove
    doctrineSubscribedEvents: ['postPersist', 'postUpdate', 'preRemove', 'postRemove'] 

@curquiza When merging this, we need to update the wiki - Indexing automaticlly via ...

@norkunas
Copy link
Collaborator

norkunas commented Jun 22, 2021

Now I remember: the thing is that doctrine before dispatching postRemove event unsets the primary key so there is an error:

In SearchableEntity.php line 85:
                                                             
  [Symfony\Component\Config\Definition\Exception\Exception]  
  Entity has no primary key                                  
                                                             

Exception trace:
  at /var/www/html/vendor/meilisearch/search-bundle/src/SearchableEntity.php:85
 MeiliSearch\Bundle\SearchableEntity->setId() at /var/www/html/vendor/meilisearch/search-bundle/src/SearchableEntity.php:52
 MeiliSearch\Bundle\SearchableEntity->__construct() at /var/www/html/vendor/meilisearch/search-bundle/src/Services/MeiliSearchService.php:337
 MeiliSearch\Bundle\Services\MeiliSearchService->makeSearchServiceResponseFrom() at /var/www/html/vendor/meilisearch/search-bundle/src/Services/MeiliSearchService.php:131
 MeiliSearch\Bundle\Services\MeiliSearchService->remove() at /var/www/html/vendor/meilisearch/search-bundle/src/EventListener/MeiliSearchIndexerSubscriber.php:47
 MeiliSearch\Bundle\EventListener\MeiliSearchIndexerSubscriber->postRemove() at /var/www/html/vendor/symfony/doctrine-bridge/ContainerAwareEventManager.php:68
 Symfony\Bridge\Doctrine\ContainerAwareEventManager->dispatchEvent() at /var/www/html/vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php:115
 Doctrine\ORM\Event\ListenersInvoker->invoke() at /var/www/html/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1251
 Doctrine\ORM\UnitOfWork->executeDeletions() at /var/www/html/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:446
 Doctrine\ORM\UnitOfWork->commit() at /var/www/html/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:378
 Doctrine\ORM\EntityManager->flush() at /var/www/html/var/cache/dev/Container52kWrqR/EntityManager_9a5be93.php:129
 Container52kWrqR\EntityManager_9a5be93->flush() at /var/www/html/src/Command/TestasCommand.php:70
 App\Command\TestasCommand->execute() at /var/www/html/vendor/symfony/console/Command/Command.php:299
 Symfony\Component\Console\Command\Command->run() at /var/www/html/vendor/symfony/console/Application.php:996
 Symfony\Component\Console\Application->doRunCommand() at /var/www/html/vendor/symfony/framework-bundle/Console/Application.php:96
 Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /var/www/html/vendor/symfony/console/Application.php:295
 Symfony\Component\Console\Application->doRun() at /var/www/html/vendor/symfony/framework-bundle/Console/Application.php:82
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /var/www/html/vendor/symfony/console/Application.php:167
 Symfony\Component\Console\Application->run() at /var/www/html/vendor/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php:56
 Symfony\Component\Runtime\Runner\Symfony\ConsoleApplicationRunner->run() at /var/www/html/vendor/autoload_runtime.php:35
 require_once() at /var/www/html/bin/console:15

@norkunas
Copy link
Collaborator

Also I've forgot about rollbacked transactions :) but that probably should follow in another PR.

@codedge codedge changed the title Option to listen to postRemove event WIP: Option to listen to postRemove event Jun 22, 2021
@codedge
Copy link
Contributor Author

codedge commented Jun 22, 2021

There are currently no tests for listening and then acting on the events coming from Doctrine. I'll add some to catch these kind of errors.

@curquiza
Copy link
Member

Thanks for your PR @codedge, request me as reviewer when you think this is finished! 🙂

@codedge codedge force-pushed the doctrine-post-remove branch from d88ea37 to 7cc5a35 Compare June 22, 2021 18:27
@codedge
Copy link
Contributor Author

codedge commented Jun 23, 2021

After some digging this is the result:

postRemove has no entity id

The postRemove event is obviously not the best choice when you need the entity id for further processing.
There is a big discussion about this here doctrine/orm#2326 with no outcome. It is just by design.

Yes, we can tackle this with some hacks, f. ex. saving the entity in some new field in the preRemove event so that we still have it in the postRemove event but that is... hacky. I am not a big fan of that.

The hack would mean that we always would need to listen to the preRemove event when the postRemove event is configured.

So using the postRemove event for removing a document from MS is likely not going to be successful. What dou you think?

Transactions

If you @norkunas can outline what your concerns are regarding? 😄

I would think if your transaction fails, meaning the removal of the entity in your db is not successful, but the preRemove event already fired and removed the document from MS - then why not adding it again?

It seems there are also new Transaction events added in Doctrine so you could catch those errors and call MS again to re-index the document.

Let me know, where I am wrong here 😉

@norkunas
Copy link
Collaborator

My primary concern was to have at least integration with messenger by adding but the problem is that SearchService does not have a method to remove document by identifier which I could handle by myself when needed with preRemove setting the ID and postRemove dispatching the message :)

@codedge
Copy link
Contributor Author

codedge commented Jun 23, 2021

I see :D Well, then we all learned a bit about Doctrine :D :D

@curquiza
Then I would still push some test for this one here and remove the postRemove config for now. Then we should move on with the messenger.

@codedge
Copy link
Contributor Author

codedge commented Jun 26, 2021

Changes in this PR are only pointing towards testing, code style (strict typings, format).

PHPstan

I added https://github.com/phpstan/phpstan for checking the coding regarding type juggling.
There is a composer script composer phpstan that start and runs phpstan.

The current level is 5, 8 are available and the more the better. For now, I think this is quite a good result.

I already added this to be a check for every PR. See my changes to the test.yml.

Separating tests

I felt like some tests are more like unit testing, most are integration tests. That's why I split them into a Unit and an Integration directory and created two test suites. That's nothing anyone will notice but it seems it gives some more structure to the testing files.

Further the unit tests can rely on the default KernelTestCase that is shipped with Symfony. I feel like sticking to the (Symfony) defaults is like a good thing.

Code style

I added the new PHP CS Fixer rule PHP80MigrationRisky which works a bit more towards stricter code/types by adding return types to methods.

Doctrine events tests & coverage

There are now doctrine event subscriber tests. The overall test coverage is about 85%.
There is additionally a composer command composer test:unit:coverage which will create the code coverage (if you have either xdebug or pcov installed).

Obosolete files

I found two files that are obsolete and used nowhere.

All the changes should be non-breaking. If you checked @curquiza feel free to merge.

@codedge codedge changed the title WIP: Option to listen to postRemove event Option to listen to postRemove event Jun 26, 2021
src/Engine.php Outdated
@@ -80,7 +80,7 @@ public function remove($searchableEntities): array
/** @var SearchableEntity $entity */
foreach ($searchableEntities as $entity) {
$searchableArray = $entity->getSearchableArray();
if (null === $searchableArray || 0 === \count($searchableArray)) {
if (null == $searchableArray || 0 == \count($searchableArray)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why this change? :)

Copy link
Contributor Author

@codedge codedge Jun 28, 2021

Choose a reason for hiding this comment

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

This change came from PHPstan stating that this comparison is always null. I prepared an example in the PHPstan playground: https://phpstan.org/r/07c0aa63-1a31-4a24-b6af-c14dffa92dc5

In the end I adjusted the code now:

  • $entity->getSearchableArray() always returns an array
  • The check of null is removed now

From time to time I am opting for PHPstan level 6, so there might be changes added that focus towards level 6.

Holger Lösken added 2 commits June 28, 2021 23:20
Copy link
Member

@curquiza curquiza left a comment

Choose a reason for hiding this comment

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

Thank you a lot everyone!!
And sorry for the delay!

bors merge

🚀

bors bot added a commit that referenced this pull request Jul 1, 2021
96: Option to listen to postRemove event r=curquiza a=codedge

This PR adds the option to listen to Doctrines `postRemove`. This is a result of the discussion in #62, a first step.

You can know specify in `meili_search.yml`:

```
meili_search:
    # One, or multiple of postPersist, postUpdate, preRemove, postRemove
    doctrineSubscribedEvents: ['postPersist', 'postUpdate', 'preRemove', 'postRemove'] 
```

@curquiza When merging this, we need to update the [wiki - Indexing automaticlly via ...](https://github.com/meilisearch/meilisearch-symfony/wiki/index-data-into-meilisearch#indexing-automatically-via-doctrine-events) 



Co-authored-by: Holger Lösken <[email protected]>
@bors
Copy link
Contributor

bors bot commented Jul 1, 2021

Timed out.

@codedge
Copy link
Contributor Author

codedge commented Jul 1, 2021

bors has its bad days 😃

@curquiza Can you create a release out of the current master branch after this is merged? My last changes regarding the installation, #94, is thing I need for the Symfony recipe. The Symfony recipe checks fails, because of the error fixed in #94 .

@curquiza
Copy link
Member

curquiza commented Jul 1, 2021

I merge without bors then, because I'm on holiday in few minutes during a month and I don't want to wait 😇

@curquiza curquiza merged commit 2fd7b74 into main Jul 1, 2021
@curquiza curquiza deleted the doctrine-post-remove branch July 1, 2021 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants