Skip to content

Commit 17a76f5

Browse files
authored
[EasyServerless] Listener for resetting Symfony services between messages (#1781)
1 parent 45f7222 commit 17a76f5

8 files changed

Lines changed: 130 additions & 5 deletions

File tree

packages/EasyServerless/bundle/EasyServerlessBundle.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ public function loadExtension(array $config, ContainerConfigurator $container, C
8383

8484
if ($this->isBundleEnabled('BrefMessengerBundle', $builder)) {
8585
$container->import('config/messenger.php');
86+
87+
if ($config['sqs']['reset_services']['enabled']) {
88+
$container->import('config/sqs_reset_services.php');
89+
}
8690
}
8791

8892
if (\class_exists(Logger::class) && $config['monolog']['enabled']) {

packages/EasyServerless/bundle/config/definition.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@
3939
->arrayNode('monolog')
4040
->canBeDisabled()
4141
->end()
42+
->arrayNode('sqs')
43+
->addDefaultsIfNotSet()
44+
->children()
45+
->arrayNode('reset_services')
46+
->canBeDisabled()
47+
->info('Enable resetting Symfony services between serverless message handling.')
48+
->end()
49+
->end()
50+
->end()
4251
->arrayNode('state')
4352
->canBeDisabled()
4453
->children()
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
5+
6+
use EonX\EasyServerless\Messenger\Listener\ResetServicesListener;
7+
8+
return static function (ContainerConfigurator $containerConfigurator): void {
9+
$services = $containerConfigurator->services();
10+
$services->defaults()
11+
->autowire()
12+
->autoconfigure();
13+
14+
$services->set(ResetServicesListener::class)
15+
->arg('$servicesResetter', service('services_resetter'));
16+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace EonX\EasyServerless\Messenger\Listener;
5+
6+
use EonX\EasyServerless\Messenger\Event\EnvelopeDispatchedEvent;
7+
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
8+
use Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter;
9+
10+
#[AsEventListener(priority: -1024)]
11+
final readonly class ResetServicesListener
12+
{
13+
public function __construct(
14+
private ServicesResetter $servicesResetter,
15+
) {
16+
}
17+
18+
public function __invoke(EnvelopeDispatchedEvent $event): void
19+
{
20+
$this->servicesResetter->reset();
21+
}
22+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
5+
6+
return static function (ContainerConfigurator $containerConfigurator): void {
7+
$containerConfigurator->extension('easy_serverless', [
8+
'sqs' => [
9+
'reset_services' => [
10+
'enabled' => false,
11+
],
12+
],
13+
]);
14+
};

packages/EasyServerless/tests/Stub/Kernel/KernelStub.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@
55

66
use Bref\Symfony\Messenger\Service\BusDriver;
77
use EonX\EasyServerless\Bundle\EasyServerlessBundle;
8+
use Psr\Log\NullLogger;
89
use Symfony\Component\Config\Loader\LoaderInterface;
10+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
911
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1012
use Symfony\Component\DependencyInjection\ContainerBuilder;
1113
use Symfony\Component\DependencyInjection\Definition;
14+
use Symfony\Component\DependencyInjection\ServiceLocator;
15+
use Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter;
1216
use Symfony\Component\HttpKernel\Kernel;
1317
use Symfony\Component\HttpKernel\KernelInterface;
18+
use Symfony\Component\Messenger\MessageBus;
19+
use Symfony\Component\Messenger\MessageBusInterface;
20+
use Symfony\Component\Messenger\Transport\Serialization\PhpSerializer;
21+
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
1422

1523
final class KernelStub extends Kernel implements CompilerPassInterface
1624
{
@@ -19,15 +27,23 @@ final class KernelStub extends Kernel implements CompilerPassInterface
1927
*/
2028
private readonly array $configs;
2129

30+
/**
31+
* @var \Symfony\Component\HttpKernel\Bundle\BundleInterface[]
32+
*/
33+
private readonly array $extraBundles;
34+
2235
/**
2336
* @param string[]|null $configs
37+
* @param \Symfony\Component\HttpKernel\Bundle\BundleInterface[]|null $bundles
2438
*/
2539
public function __construct(
2640
string $environment,
2741
bool $debug,
2842
?array $configs = null,
43+
?array $bundles = null,
2944
) {
3045
$this->configs = $configs ?? [];
46+
$this->extraBundles = $bundles ?? [];
3147

3248
parent::__construct($environment, $debug);
3349
}
@@ -40,6 +56,23 @@ public function process(ContainerBuilder $container): void
4056
);
4157
$container->setAlias(KernelInterface::class, 'kernel');
4258
$container->setDefinition(BusDriver::class, new Definition(BusDriver::class));
59+
$container->setDefinition(NullLogger::class, new Definition(NullLogger::class));
60+
$container->setAlias('logger', NullLogger::class);
61+
$container->setDefinition(
62+
MessageBus::class,
63+
(new Definition(MessageBus::class))->setArguments([[]])
64+
);
65+
$container->setAlias(MessageBusInterface::class, MessageBus::class);
66+
$container->setDefinition(PhpSerializer::class, new Definition(PhpSerializer::class));
67+
$container->setAlias(SerializerInterface::class, PhpSerializer::class);
68+
$container->setDefinition(
69+
'messenger.retry_strategy_locator',
70+
(new Definition(ServiceLocator::class))->setArguments([[]])
71+
);
72+
$container->setDefinition(
73+
'services_resetter',
74+
(new Definition(ServicesResetter::class))->setArguments([new IteratorArgument([]), []])
75+
);
4376

4477
foreach ($container->getDefinitions() as $definition) {
4578
$definition->setPublic(true);
@@ -56,6 +89,10 @@ public function process(ContainerBuilder $container): void
5689
public function registerBundles(): iterable
5790
{
5891
yield new EasyServerlessBundle();
92+
93+
foreach ($this->extraBundles as $bundle) {
94+
yield $bundle;
95+
}
5996
}
6097

6198
public function registerContainerConfiguration(LoaderInterface $loader): void

packages/EasyServerless/tests/Unit/AbstractSymfonyTestCase.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ abstract class AbstractSymfonyTestCase extends AbstractUnitTestCase
1212

1313
/**
1414
* @param string[]|null $configs
15+
* @param \Symfony\Component\HttpKernel\Bundle\BundleInterface[]|null $bundles
1516
*/
16-
protected function getKernel(?array $configs = null): KernelInterface
17+
protected function getKernel(?array $configs = null, ?array $bundles = null): KernelInterface
1718
{
18-
if ($this->kernel !== null && $configs === null) {
19+
if ($this->kernel !== null && $configs === null && $bundles === null) {
1920
return $this->kernel;
2021
}
2122

22-
$this->kernel = new KernelStub('test', true, $configs);
23+
$this->kernel = new KernelStub('test', true, $configs, $bundles);
2324
$this->kernel->boot();
2425

2526
return $this->kernel;

packages/EasyServerless/tests/Unit/bundle/EasyServerlessBundleTest.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,42 @@
33

44
namespace EonX\EasyServerless\Tests\Unit\Bundle;
55

6+
use Bref\Symfony\Messenger\BrefMessengerBundle;
67
use EonX\EasyServerless\Bundle\Enum\ConfigParam;
8+
use EonX\EasyServerless\Messenger\Listener\ResetServicesListener;
79
use EonX\EasyServerless\Monolog\Processor\PhpSourceProcessor;
810
use EonX\EasyServerless\Tests\Unit\AbstractSymfonyTestCase;
911

1012
final class EasyServerlessBundleTest extends AbstractSymfonyTestCase
1113
{
1214
public function testDisableMonologSucceeds(): void
1315
{
14-
$container = $this->getKernel([__DIR__ . '/../../Fixture/config/monolog_disabled.php'])
15-
->getContainer();
16+
$container = $this->getKernel(
17+
configs: [__DIR__ . '/../../Fixture/config/monolog_disabled.php']
18+
)->getContainer();
1619

1720
self::assertFalse($container->has(PhpSourceProcessor::class));
1821
}
1922

23+
public function testDisableResetServicesSucceeds(): void
24+
{
25+
$container = $this->getKernel(
26+
configs: [__DIR__ . '/../../Fixture/config/sqs_reset_services_disabled.php'],
27+
bundles: [new BrefMessengerBundle()]
28+
)->getContainer();
29+
30+
self::assertFalse($container->has(ResetServicesListener::class));
31+
}
32+
33+
public function testResetServicesEnabledByDefault(): void
34+
{
35+
$container = $this->getKernel(
36+
bundles: [new BrefMessengerBundle()]
37+
)->getContainer();
38+
39+
self::assertTrue($container->has(ResetServicesListener::class));
40+
}
41+
2042
public function testSanity(): void
2143
{
2244
$container = $this->getKernel()

0 commit comments

Comments
 (0)