Skip to content

Make the EntityManager resettable #5933

@stof

Description

@stof

In Doctrine ORM 2.x, when an exception occurs during a flush, the EntityManager gets closed, because its unit of work is in a broken state.
But once it is closed, the object becomes totally unusable. This makes the EntityManager really hard to use in a context where you rely on dependency injection, because replacing the EntityManager with a new (non closed) instance would also mean replacing all the objects depending on it in the object graph (transitively).
This may not be a big issue for normal HTTP request handling (where each request is a separate process and the exception closing the EM tends to mark the end of the request), but it is critical for usage in a long-running process (for instance a RabbitMQ consumer).

The way we are dealing with it in 2.x is to never inject the EM directly, but to inject the ManagerRegistry instead, and to always get the EM from it (and never storing it in a property as it would reproduce the issue). We have the same restriction for entity repositories.
This allows replacing the entity manager (because there is a single object depending on it directly in the graph, which is the ManagerRegistry, and this class is designed to be able to reset the EM in it without replacing the registry itself). But it makes the architecture very fragile (it is easy to leak a place using the EM directly).

Btw, the AbstractManagerRegistry shipped in Doctrine Common lets implementation reset the manager (as the knowledge about retrieving the EM instance is part of the implementation work too). And the way this is implemented in Symfony today relies on being able to reset services in the DIC as if they were never instantiated, which is something we want to deprecated in Symfony 3.2. So we are currently looking at wrapping the EM in a proxy object to make it resettable by deinitializing the proxy (see symfony/symfony#19203 for the implementation). The drawback is that this forces to add overhead on calls to the EntityManager class. The advantage is that it solves the issue for object graph depending on the EM (but not for objects instantiated by Doctrine itself, like the entity repositories, because passing $this to the new instance does not play well with decorators) and that it avoids using our deprecated APIs.

So it would be really great that the EntityManager (actually the UnitOfWork IIRC) could be reset to reopen it (the unit of work would get cleared).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions