Skip to content

Commit

Permalink
Enhance connection closed by EM stracktrace.
Browse files Browse the repository at this point in the history
  • Loading branch information
ptondereau authored and gaelreyrol committed Feb 5, 2024
1 parent 40fbbf4 commit 6a348d6
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 9 deletions.
5 changes: 3 additions & 2 deletions src/Decorator/EntityManagerDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Persistence\ObjectManagerDecorator;
use Throwable;

use function func_get_arg;
use function func_num_args;
Expand Down Expand Up @@ -184,9 +185,9 @@ public function getPartialReference($entityName, $identifier)
/**
* {@inheritDoc}
*/
public function close()
public function close(?Throwable $e = null)
{
$this->wrapped->close();
$this->wrapped->close($e);
}

/**
Expand Down
12 changes: 8 additions & 4 deletions src/EntityManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ class EntityManager implements EntityManagerInterface
*/
private $cache;

/** @var EntityManagerClosed|null */
private $closedWhere = null;

/**
* Creates a new EntityManager that operates on the given database connection
* and uses the given Configuration and EventManager implementations.
Expand Down Expand Up @@ -254,7 +257,7 @@ public function transactional($func)

return $return ?: true;
} catch (Throwable $e) {
$this->close();
$this->close($e);
$this->conn->rollBack();

throw $e;
Expand Down Expand Up @@ -637,11 +640,12 @@ public function clear($entityName = null)
/**
* {@inheritDoc}
*/
public function close()
public function close(?Throwable $e = null)
{
$this->clear();

$this->closed = true;
$this->closed = true;
$this->closedWhere = EntityManagerClosed::createClosedHere($e);
}

/**
Expand Down Expand Up @@ -880,7 +884,7 @@ public function getConfiguration()
private function errorIfClosed(): void
{
if ($this->closed) {
throw EntityManagerClosed::create();
throw EntityManagerClosed::createWhere($this->closedWhere);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/EntityManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Doctrine\ORM\Query\FilterCollection;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Persistence\ObjectManager;
use Throwable;

/**
* EntityManager interface
Expand Down Expand Up @@ -220,7 +221,7 @@ public function getPartialReference($entityName, $identifier);
*
* @return void
*/
public function close();
public function close(?Throwable $e = null);

/**
* Creates a copy of the given entity. Can create a shallow or a deep copy.
Expand Down
28 changes: 28 additions & 0 deletions src/Exception/EntityManagerClosed.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,38 @@

namespace Doctrine\ORM\Exception;

use Throwable;

final class EntityManagerClosed extends ORMException implements ManagerException
{
public static function create(): self
{
return new self('The EntityManager is closed.');
}

public static function createWhere(?Throwable $e = null): self
{
if ($e === null) {
return self::create();
}

return new self(
'The EntityManager is closed (previous allows to trace back to where it was closed).',
0,
$e
);
}

public static function createClosedHere(?Throwable $cause = null): self
{
if ($cause === null) {
return new self('This exception allows to trace back to where close() was called.');
}

return new self(
'This exception allows to trace back to where close() was called (see previous exception for the cause).',
0,
$cause
);
}
}
5 changes: 3 additions & 2 deletions tests/Performance/Mock/NonProxyLoadingEntityManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Proxy\ProxyFactory;
use Doctrine\ORM\Query\ResultSetMapping;
use Throwable;

/**
* An entity manager mock that prevents lazy-loading of proxies
Expand Down Expand Up @@ -183,9 +184,9 @@ public function getPartialReference($entityName, $identifier)
/**
* {@inheritDoc}
*/
public function close()
public function close(?Throwable $e = null)
{
$this->realEntityManager->close();
$this->realEntityManager->close($e);
}

/**
Expand Down
10 changes: 10 additions & 0 deletions tests/Tests/ORM/Decorator/EntityManagerDecoratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Doctrine\ORM\Decorator\EntityManagerDecorator;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\ResultSetMapping;
use Exception;
use Generator;
use LogicException;
use PHPUnit\Framework\MockObject\MockObject;
Expand Down Expand Up @@ -80,6 +81,15 @@ static function (): void {
];
}

if ($method->getName() === 'close') {
return [
$method->getName(),
[
new Exception(),
],
];
}

$parameters = [];

foreach ($method->getParameters() as $parameter) {
Expand Down

0 comments on commit 6a348d6

Please sign in to comment.