mirror of
https://github.com/doctrine/orm.git
synced 2026-03-24 06:52:09 +01:00
Add support for object pools / context #7582
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @lyrixx on GitHub (Dec 23, 2025).
RFC: Independent Persistence Contexts (Persistence Pools)
Abstract
This RFC proposes a mechanism to create isolated "pools" or "sub-contexts" within the
EntityManager. The goal is to allow developers topersistandflushspecific entities without interfering with the globalUnitOfWorkstate.Problem Statement
In many scenarios, developers need to perform "side-effect" writes that are independent of the main business transaction.
Current issues:
$em->flush()persists every scheduled change in theUnitOfWork. If the main transaction has pending invalid entities, the side-effect write fails.$em->flush($entity)is deprecated or discouraged because it doesn't guarantee consistency and ignores manyUnitOfWorkstates.Use Cases
last_used_attimestamp on an API token without flushing the entire user profile.Proposed Solution
Introduce a
ContextorPoolobject that acts as a lightweight, isolatedUnitOfWork.Benefits
EntityManager.Notes
It might be possible with 2 EM, but I'll lead to the same issue. The "internal" EM could have many pending changes
It might be possible with nested transaction, but I'm not sure it has been built for this use case
WDYT ?
@VincentLanglet commented on GitHub (Jan 1, 2026):
Let's say I have to also add the current User doing the modification to the AuditLog, how you deal with this situation ?
The second solution might be the simplest to have a perfect isolation but I feel like in real life it will just force the developper to "duplicate" the ownership of the managed entity. It also introduce some weird question about what if a pool is updating a value about the user while the "original" entity manager still have the "old" managed entity.
A similar/related topic is the "Cascade" configuration, does the "Cascade persist" is applied to pool/context or only to the original entityManager ? I.E. if I write
Does the pool will just persist a new AuditLog related to the User, but still does not flush the user firstName (since I didn't persist the
$userchanges) or does persisting the log will cascade-persist the user ?@beberlei commented on GitHub (Jan 4, 2026):
I am thinking about this problem for a long time now, and had different ideas as well.
From a naming perspective, i would consider using
Transactionand variants, looking at inspiration from the TransactionStatus API from JPA.Initially an idea was this API, but there are other more recent ideas that are not ready to share: https://gist.github.com/beberlei/4b39c4ed1f172890e03fc6e2fa83146e
One thought I had is that maybe switching the change tracking policy from implicit to explicit for certain use-cases could work.
But recently from the Doctrine hackathon we also started considering to replace the UnitOfWork in clear to get rid of the "EM is closed" state, which could also open the door to multiple UnitOfWorks.
However there are a lot of potentially ugly edge cases around this, as Vincent also points out.
@beberlei commented on GitHub (Jan 4, 2026):
Related https://github.com/doctrine/orm/issues/5933
@stof commented on GitHub (Jan 6, 2026):
having multiple active unit of work is totally different from the case of replacing the unit of work to re-open a closed entity manager.
Multiple active unit of work have issues regarding the ownership of change tracking (either they both manage the same entity instance, which can create weird cases, or they require using separate entity instances but this leads to the possibility of mutating those instances in non-synchronized ways).
@lyrixx commented on GitHub (Jan 7, 2026):
@VincentLanglet I would forbid your first example. I'll lead to headache, and it defeats the purpose. Second option is the say to go!
@stof commented on GitHub (Jan 7, 2026):
@lyrixx but in that second option, you can have 2 different manager
Userinstance for the id 42, one on the main entity manager and one in the pool. If the pool saves a change in the DB for that id, the instance in the main entity manager won't reflect it. And this becomes even worse if the pool deletes that row, as the main entity manager now has a managed instance that corresponds to no row in the DB (causing weird things when saving changes).And things become even worse in case the main entity manager has an uninitialized lazy instance for the id 42 and the pool deletes that row.
@lyrixx commented on GitHub (Jan 7, 2026):
yes! No magic here. Anyway, usually, my use cases are really limited, and have a really narrow scoped.
For example, in a log line, there is never a strong relation to another entity. Like in an invoice. You don't want to loose something if a user unregister.
Anyway, the Benjamin RFC looks nice