Skip to content

[Messenger] Add clear Entity Manager middleware #31334

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

Conversation

Koc
Copy link
Contributor

@Koc Koc commented Apr 30, 2019

Q A
Branch? 4.4
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #29662
License MIT
Doc PR TBD

General purpose of this middleware:

  • avoid memory leaks during messages handling
  • prevent unexpected side effects when entities that already stored in identity map not refreshed between messages

@Koc Koc force-pushed the feature/messenger-clear-entity-manager-middleware branch 3 times, most recently from 4c30a13 to 8c03f5f Compare May 10, 2019 08:20
@Koc Koc force-pushed the feature/messenger-clear-entity-manager-middleware branch from 8c03f5f to 42ac426 Compare May 12, 2019 11:13
@Koc Koc force-pushed the feature/messenger-clear-entity-manager-middleware branch 2 times, most recently from 1a25291 to 5d2b022 Compare May 29, 2019 19:12
@Koc Koc changed the base branch from master to 4.4 May 29, 2019 19:13
@Koc
Copy link
Contributor Author

Koc commented May 29, 2019

I've switched branch to 4.4, tests are green.

@Koc Koc force-pushed the feature/messenger-clear-entity-manager-middleware branch from 5d2b022 to 6e690a6 Compare June 3, 2019 15:45
@Koc
Copy link
Contributor Author

Koc commented Jun 3, 2019

Status: Needs Review

@fabpot
Copy link
Member

fabpot commented Jun 4, 2019

Thank you @Koc.

@fabpot fabpot merged commit 6e690a6 into symfony:4.4 Jun 4, 2019
fabpot added a commit that referenced this pull request Jun 4, 2019
This PR was merged into the 4.4 branch.

Discussion
----------

[Messenger] Add clear Entity Manager middleware

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #29662
| License       | MIT
| Doc PR        | TBD

General purpose of this middleware:
* avoid memory leaks during messages handling
* prevent unexpected side effects when entities that already stored in identity map not refreshed between messages

Commits
-------

6e690a6 Add clear Entity Manager middleware (closes #29662)
@Koc Koc deleted the feature/messenger-clear-entity-manager-middleware branch July 16, 2019 20:07
*
* @author Konstantin Myakshin <molodchick@gmail.com>
*/
class DoctrineClearEntityManagerMiddleware implements MiddlewareInterface
Copy link
Contributor

Choose a reason for hiding this comment

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

why not final?

@Stoakes
Copy link

Stoakes commented Oct 20, 2019

I discovered this PR through Symfony blog post, and tried code of this PR on a Symfony 4.3 project.

This middleware is correctly called by messenger:consume but also when a message is sent, which has a few disagreements. For instance, entities are cleared after a dispatch. Therefore when doing something similar to: (which works fine without the middleware)

     // get whatever user in $user variable
    $message = new SendEmailCommand();
    // Perform whatever business logic and add a stamp
    $e = new Envelope($message, [new DelayHeader($delay)]);
    $this->bus->dispatch($e);
    
    // Applicative log in database that a message has been sent. I naively expect $user to still be available and known from the entity manager
    $this->userLogger->userLog($user, 'send_email_command',"sent message with a delay of $delay seconds");

now produce the following error message

HTTP 500 Internal Server Error
A new entity was found through the relationship 'App\Entity\User\AppLog#user' that was not configured to cascade persist operations for entity: 13 stoakes. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).

I can workaround it in my application, but I'm not sure this is a desirable feature to have this middleware called when a message is sent. Is there a way to use this middleware only when unning consumer and not when sending message ?

Edit: after some more search, a similar discussion goes on #32436

@weaverryan
Copy link
Member

See #34066

fabpot added a commit that referenced this pull request Oct 22, 2019
…ng always (weaverryan)

This PR was merged into the 4.4 branch.

Discussion
----------

[Messenger] Fix worker-only Doctrine middleware from running always

| Q             | A
| ------------- | ---
| Branch?       | 4.4 (or 4.3?, this is a bug fix)
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #32436 Depends on #34069
| License       | MIT
| Doc PR        | not needed

Several Doctrine middleware are only meant to be run in a "worker" context: we want to "ping" the connection, "close" the connection and "clear" the entity manager ONLY when we are receiving messages. Before this PR, it was done always, which causes bad behavior for sync messages (imagine your Doctrine connection being closed in the middle of a controller or see #31334 (comment)).

This fixes that in a pragmatic way: no new system for "worker-only" middleware or anything like that: just make the middleware smart enough to only do their work when a message is being received async.

Commits
-------

290a729 Fixing issue where worker-only middleware were run in all contexts
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.4 Oct 27, 2019
This was referenced Nov 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants