-
-
Notifications
You must be signed in to change notification settings - Fork 455
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
Weird behaviour due to EM resets after update to 2.0.6 #1114
Comments
@dnna that's correct, we shouldn't clear in php-pm if things are working good on doctrine. But besides the weird behaviour, a full reset of the manager is not needed after every request, a simple clear should be enough unless the manager has been closed. |
My guess is the issue was introduced with #1108, which was merged with 2.0.5. @acasademont out of curiosity could you try with 2.0.4 to make sure the issue is not occurring there? |
AFAIK this was first introduced in 2.0.3 2.0.2...2.0.3 and was later fixed for the LazyLoading case afterwards, but the reset behaviour is the same, that's why we reverted to 2.0.2 |
AFAIK the
Is it possible that your first ORM query runs somehow before the reset function in the kernel executes, so it uses the old manager? |
Not really, the reset is done on kernel boot, nothing has happened before that. I believe is more of an issue of how the SF container manages dependencies and services. Something similar seems to be happening in #1112 |
should be resolved by using |
Just updated doctrine/doctrine-bundle (2.0.2 => 2.0.6) and encountered this bug, 16 tests are down :)
Reverted back to 2.0.2 Edited: btw, I'm using |
I don't see how your suggestion with We could also use a reproducer, as description of issue is quite strange too. I don't see how how can reset happen while first query did not finish yet, that looks like some missed locking opportunity in php-pmhttpkernel. |
@ostrolucky they are 2 independent things I believe. On the one hand, the weird behaviour which I don't really yet fully underestand why is it happening. On the other, that besides the issue, a full reset is not needed for what we're trying to achieve, a clear() should be enough. We've been using it for a very long time without any problems in php-pm. |
I would argue opposite. Class can have other side effects due to internal state not properly reset. Especially when using custom EMs. Meanwhile, waiting for more information to troubleshoot the issue as I don't see how we can help otherwise. |
@ostrolucky the logic for deciding reset vs clear is on the Registry, not the bridge, https://github.com/doctrine/DoctrineBundle/blob/master/Registry.php#L59 @stof already raised the question (unanswered) of why we couldn't clear instead of reset the whole thing on the PR #1099 (comment) But anyways, this is not what this issue is about. |
Some more info. Seems like the first doctrine query from the Security fetch is done with the old entity manager, then it gets actually reset (due to the lazy proxy it's not reset immediately).
The question is: why that first Doctrine query is not invoking the Proxy method that would trigger the reset? |
ok @ostrolucky I think I got it. See this code class A {
private $repository;
public function __construct($em)
{
$this->repository = $em->getRepository('Foo');
}
public function getA($a)
{
return $this->repository->find($a);
}
}
class B {
private $em;
public function __construct($em)
{
$this->em = $em;
}
public function getA($a)
{
return $this->em->find('Foo', $a);
}
} Imagine we have these 2 classes, with different ways of accessing the same entity On class A, the EM is injected but then the Repository is left as a property of A and all queries go through that repo. On class B, the EM is left as a property and all queryies go directly through the EM. On the first request, all is fine! On the second request, at the beginning, the EM is reset. As the EM is a LazyProxy, the way of resetting it is that it will create a new instance of EM once an EM method is accessed. However, on the second request, class A will still be using the old EM, it will never be reset, as no method of the proxy is ever called that forces to "reinstantiate". On class B, every request will reinstantiate the EM. Therefore, on the second request, we end up using 2 different EMs, with different UoW and different entityMaps. And that causes the weird behaviour I reported. It shouldn't be hard to replicate this in a test, hope the issue is a bit more clear now. |
But what is the solution in this case (aside from rewriting the app to inject the Registry instead of Manager and setting that as the property)? It seems the PHP-PM method has worked because it basically never replaces the EM under normal circumstances (it performs clear unless an error occurred that caused the EM to close). If it always performed a reset instead of clear we would have observed the same issue as we do here. In my opinion we should use clear in this bundle too (similar code to what PHP-PM uses) or revert this change and reserve for a major release, as the current reset method IMHO is causing a BC break. |
@dnna indeed, I just replicated the same behaviour with Doctrine 2.0.2 by forcing an EM closing (a DB exception while flushing changes) on the previous request. This is a deeper issue I'm afraid. The EM reset mechanism is not really working as expected. It's just that now this is more evident due to the forced EM resets after every request. As you pointed, there are 2 solutions:
|
The duplicate service issue is fixed by #1118 which will be released as 1.12.7 and 2.0.7 soon. We're still evaluating how to proceed with the other breaks caused by clearing the manager. |
Hi,
PHP-PM used to manually reset or clear the entity manager after every request (https://github.com/php-pm/php-pm-httpkernel/blob/master/Bootstraps/Symfony.php#L168). Now it seems like Symfony is able to automatically do it thanks to the
kernel.reset
tag but we're seeing a very strange behaviour.On the first request all is fine,
On the second request, the EntityManager is reset at the beginning of the request, but the first ORM query is still going to the old EntityManager. The second ORM query sees that the manager has been reset, and instantiates another EM/UnitOfWork, effectively clearing the entityStates cache, which is bad, because in my code I have an entity created by the first query that the newly created UnitOfWork doesn't know anything about. If it is persisted, it will try an INSERT, instead of an UPDATE :(
To be honest, I don't really understand why the first ORM query after the reset is still using the old EM/UnitOfWork.
In any case, the EM shouldn't be reset after every request, a simple clear should be enough unless the EM hasn't been closed due to an Exception. In that case, yes, the manager should be reset. We've been working with that code in PHP-PM for a very long time and it works pretty well.
We've reverted to 2.0.2 in the meantime, but I'm not entirely sure how to solve this issue going forward.
The text was updated successfully, but these errors were encountered: