Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 67e1709

Browse filesBrowse files
committed
feature #31061 [BridgeDoctrineMessenger] Doctrine ping connection middleware (insidestyles)
This PR was squashed before being merged into the 4.3-dev branch (closes #31061). Discussion ---------- [BridgeDoctrineMessenger] Doctrine ping connection middleware | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? | no <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tests pass? | yes <!-- please add some, will be required by reviewers --> | Fixed tickets | #... <!-- #-prefixed issue number(s), if any --> | License | MIT | Doc PR | symfony/symfony-docs#... <!-- required for new features --> - Check and reconnect if mysql has gone away: <service id="messenger.middleware.doctrine_ping_connection" class="Symfony\Bridge\Doctrine\Messenger\DoctrinePingConnectionMiddleware" public="false"> <argument type="service" id="doctrine" /> </service> - Close and save opened connections (not active worker): <service id="messenger.middleware.doctrine_close_connection" class="Symfony\Bridge\Doctrine\Messenger\DoctrineCloseConnectionMiddleware" public="false"> <argument type="service" id="doctrine" /> </service> Commits ------- 6fd9f6a [BridgeDoctrineMessenger] Doctrine ping connection middleware
2 parents 96a7907 + 6fd9f6a commit 67e1709
Copy full SHA for 67e1709

5 files changed

+248
-0
lines changed

‎src/Symfony/Bridge/Doctrine/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ CHANGELOG
77
* changed guessing of DECIMAL to set the `input` option of `NumberType` to string
88
* deprecated not passing an `IdReader` to the `DoctrineChoiceLoader` when query can be optimized with a single id field
99
* deprecated passing an `IdReader` to the `DoctrineChoiceLoader` when entities have a composite id
10+
* added `DoctrinePingConnectionMiddleware`
11+
* added `DoctrineCloseConnectionMiddleware`
1012

1113
4.2.0
1214
-----
+57Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Messenger;
13+
14+
use Doctrine\Common\Persistence\ManagerRegistry;
15+
use Doctrine\ORM\EntityManagerInterface;
16+
use Symfony\Component\Messenger\Envelope;
17+
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
18+
use Symfony\Component\Messenger\Middleware\StackInterface;
19+
20+
/**
21+
* Closes connection and therefore saves number of connections.
22+
*
23+
* @author Fuong <insidestyles@gmail.com>
24+
*
25+
* @experimental in 4.3
26+
*/
27+
class DoctrineCloseConnectionMiddleware implements MiddlewareInterface
28+
{
29+
private $managerRegistry;
30+
private $entityManagerName;
31+
32+
public function __construct(ManagerRegistry $managerRegistry, string $entityManagerName = null)
33+
{
34+
$this->managerRegistry = $managerRegistry;
35+
$this->entityManagerName = $entityManagerName;
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function handle(Envelope $envelope, StackInterface $stack): Envelope
42+
{
43+
$entityManager = $this->managerRegistry->getManager($this->entityManagerName);
44+
45+
if (!$entityManager instanceof EntityManagerInterface) {
46+
throw new \InvalidArgumentException(sprintf('The ObjectManager with name "%s" must be an instance of EntityManagerInterface', $this->entityManagerName));
47+
}
48+
49+
try {
50+
$connection = $entityManager->getConnection();
51+
52+
return $stack->next()->handle($envelope, $stack);
53+
} finally {
54+
$connection->close();
55+
}
56+
}
57+
}
+62Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Messenger;
13+
14+
use Doctrine\Common\Persistence\ManagerRegistry;
15+
use Doctrine\ORM\EntityManagerInterface;
16+
use Symfony\Component\Messenger\Envelope;
17+
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
18+
use Symfony\Component\Messenger\Middleware\StackInterface;
19+
20+
/**
21+
* Checks whether the connection is still open or reconnects otherwise.
22+
*
23+
* @author Fuong <insidestyles@gmail.com>
24+
*
25+
* @experimental in 4.3
26+
*/
27+
class DoctrinePingConnectionMiddleware implements MiddlewareInterface
28+
{
29+
private $managerRegistry;
30+
private $entityManagerName;
31+
32+
public function __construct(ManagerRegistry $managerRegistry, string $entityManagerName = null)
33+
{
34+
$this->managerRegistry = $managerRegistry;
35+
$this->entityManagerName = $entityManagerName;
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function handle(Envelope $envelope, StackInterface $stack): Envelope
42+
{
43+
$entityManager = $this->managerRegistry->getManager($this->entityManagerName);
44+
45+
if (!$entityManager instanceof EntityManagerInterface) {
46+
throw new \InvalidArgumentException(sprintf('The ObjectManager with name "%s" must be an instance of EntityManagerInterface', $this->entityManagerName));
47+
}
48+
49+
$connection = $entityManager->getConnection();
50+
51+
if (!$connection->ping()) {
52+
$connection->close();
53+
$connection->connect();
54+
}
55+
56+
if (!$entityManager->isOpen()) {
57+
$this->managerRegistry->resetManager($this->entityManagerName);
58+
}
59+
60+
return $stack->next()->handle($envelope, $stack);
61+
}
62+
}
+53Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Tests\Messenger;
13+
14+
use Doctrine\Common\Persistence\ManagerRegistry;
15+
use Doctrine\DBAL\Connection;
16+
use Doctrine\ORM\EntityManagerInterface;
17+
use Symfony\Bridge\Doctrine\Messenger\DoctrineCloseConnectionMiddleware;
18+
use Symfony\Component\Messenger\Envelope;
19+
use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase;
20+
21+
class DoctrineCloseConnectionMiddlewareTest extends MiddlewareTestCase
22+
{
23+
private $connection;
24+
private $entityManager;
25+
private $managerRegistry;
26+
private $middleware;
27+
private $entityManagerName = 'default';
28+
29+
protected function setUp()
30+
{
31+
$this->connection = $this->createMock(Connection::class);
32+
33+
$this->entityManager = $this->createMock(EntityManagerInterface::class);
34+
$this->entityManager->method('getConnection')->willReturn($this->connection);
35+
36+
$this->managerRegistry = $this->createMock(ManagerRegistry::class);
37+
$this->managerRegistry->method('getManager')->willReturn($this->entityManager);
38+
39+
$this->middleware = new DoctrineCloseConnectionMiddleware(
40+
$this->managerRegistry,
41+
$this->entityManagerName
42+
);
43+
}
44+
45+
public function testMiddlewareCloseConnection()
46+
{
47+
$this->connection->expects($this->once())
48+
->method('close')
49+
;
50+
51+
$this->middleware->handle(new Envelope(new \stdClass()), $this->getStackMock());
52+
}
53+
}
+74Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Tests\Messenger;
13+
14+
use Doctrine\Common\Persistence\ManagerRegistry;
15+
use Doctrine\DBAL\Connection;
16+
use Doctrine\ORM\EntityManagerInterface;
17+
use Symfony\Bridge\Doctrine\Messenger\DoctrinePingConnectionMiddleware;
18+
use Symfony\Component\Messenger\Envelope;
19+
use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase;
20+
21+
class DoctrinePingConnectionMiddlewareTest extends MiddlewareTestCase
22+
{
23+
private $connection;
24+
private $entityManager;
25+
private $managerRegistry;
26+
private $middleware;
27+
private $entityManagerName = 'default';
28+
29+
protected function setUp()
30+
{
31+
$this->connection = $this->createMock(Connection::class);
32+
33+
$this->entityManager = $this->createMock(EntityManagerInterface::class);
34+
$this->entityManager->method('getConnection')->willReturn($this->connection);
35+
36+
$this->managerRegistry = $this->createMock(ManagerRegistry::class);
37+
$this->managerRegistry->method('getManager')->willReturn($this->entityManager);
38+
39+
$this->middleware = new DoctrinePingConnectionMiddleware(
40+
$this->managerRegistry,
41+
$this->entityManagerName
42+
);
43+
}
44+
45+
public function testMiddlewarePingOk()
46+
{
47+
$this->connection->expects($this->once())
48+
->method('ping')
49+
->willReturn(false);
50+
51+
$this->connection->expects($this->once())
52+
->method('close')
53+
;
54+
$this->connection->expects($this->once())
55+
->method('connect')
56+
;
57+
58+
$this->middleware->handle(new Envelope(new \stdClass()), $this->getStackMock());
59+
}
60+
61+
public function testMiddlewarePingResetEntityManager()
62+
{
63+
$this->entityManager->expects($this->once())
64+
->method('isOpen')
65+
->willReturn(false)
66+
;
67+
$this->managerRegistry->expects($this->once())
68+
->method('resetManager')
69+
->with($this->entityManagerName)
70+
;
71+
72+
$this->middleware->handle(new Envelope(new \stdClass()), $this->getStackMock());
73+
}
74+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.