Created middleware which closes DB connection after every request

This commit is contained in:
Alejandro Celaya 2018-11-24 12:49:25 +01:00
parent 2fc2ad98aa
commit ccbc6c7a75
5 changed files with 104 additions and 8 deletions

View File

@ -1,7 +1,7 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
use Shlinkio\Shlink\Common; use function Shlinkio\Shlink\Common\env;
return [ return [
@ -10,9 +10,9 @@ return [
'proxies_dir' => 'data/proxies', 'proxies_dir' => 'data/proxies',
], ],
'connection' => [ 'connection' => [
'user' => Common\env('DB_USER'), 'user' => env('DB_USER'),
'password' => Common\env('DB_PASSWORD'), 'password' => env('DB_PASSWORD'),
'dbname' => Common\env('DB_NAME', 'shlink'), 'dbname' => env('DB_NAME', 'shlink'),
'charset' => 'utf8', 'charset' => 'utf8',
], ],
], ],

View File

@ -10,10 +10,18 @@ return [
'middleware_pipeline' => [ 'middleware_pipeline' => [
'pre-routing' => [ 'pre-routing' => [
'middleware' => [ 'middleware' => (function () {
$middleware = [
ErrorHandler::class, ErrorHandler::class,
Expressive\Helper\ContentLengthMiddleware::class, Expressive\Helper\ContentLengthMiddleware::class,
], ];
if (Common\Exec\ExecutionContext::currentContextIsSwoole()) {
$middleware[] = Common\Middleware\CloseDbConnectionMiddleware::class;
}
return $middleware;
})(),
'priority' => 12, 'priority' => 12,
], ],
'pre-routing-rest' => [ 'pre-routing-rest' => [

View File

@ -31,6 +31,7 @@ return [
Template\Extension\TranslatorExtension::class => ConfigAbstractFactory::class, Template\Extension\TranslatorExtension::class => ConfigAbstractFactory::class,
Middleware\LocaleMiddleware::class => ConfigAbstractFactory::class, Middleware\LocaleMiddleware::class => ConfigAbstractFactory::class,
Middleware\CloseDbConnectionMiddleware::class => ConfigAbstractFactory::class,
IpAddress::class => Middleware\IpAddressMiddlewareFactory::class, IpAddress::class => Middleware\IpAddressMiddlewareFactory::class,
Image\ImageBuilder::class => Image\ImageBuilderFactory::class, Image\ImageBuilder::class => Image\ImageBuilderFactory::class,
@ -78,6 +79,7 @@ return [
Template\Extension\TranslatorExtension::class => ['translator'], Template\Extension\TranslatorExtension::class => ['translator'],
Middleware\LocaleMiddleware::class => ['translator'], Middleware\LocaleMiddleware::class => ['translator'],
Middleware\CloseDbConnectionMiddleware::class => ['em'],
IpGeolocation\IpApiLocationResolver::class => ['httpClient'], IpGeolocation\IpApiLocationResolver::class => ['httpClient'],
IpGeolocation\GeoLite2LocationResolver::class => [Reader::class], IpGeolocation\GeoLite2LocationResolver::class => [Reader::class],

View File

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Common\Middleware;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class CloseDbConnectionMiddleware implements MiddlewareInterface
{
/** @var EntityManagerInterface */
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
/**
* Process an incoming server request and return a response, optionally delegating
* response creation to a handler.
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$handledRequest = $handler->handle($request);
$this->em->getConnection()->close();
return $handledRequest;
}
}

View File

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\Common\Middleware;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Common\Middleware\CloseDbConnectionMiddleware;
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequestFactory;
class CloseDbConnectionMiddlewareTest extends TestCase
{
/** @var CloseDbConnectionMiddleware */
private $middleware;
/** @var ObjectProphecy */
private $handler;
/** @var ObjectProphecy */
private $em;
public function setUp()
{
$this->handler = $this->prophesize(RequestHandlerInterface::class);
$this->em = $this->prophesize(EntityManagerInterface::class);
$this->middleware = new CloseDbConnectionMiddleware($this->em->reveal());
}
/**
* @test
*/
public function connectionIsClosedWhenMiddlewareIsProcessed()
{
$req = ServerRequestFactory::fromGlobals();
$resp = new Response();
$conn = $this->prophesize(Connection::class);
$closeConn = $conn->close()->will(function () {
});
$getConn = $this->em->getConnection()->willReturn($conn->reveal());
$handle = $this->handler->handle($req)->willReturn($resp);
$result = $this->middleware->process($req, $this->handler->reveal());
$this->assertSame($result, $resp);
$getConn->shouldHaveBeenCalledOnce();
$closeConn->shouldHaveBeenCalledOnce();
$handle->shouldHaveBeenCalledOnce();
}
}