diff --git a/config/test/test_config.global.php b/config/test/test_config.global.php index 31f53e28..24057833 100644 --- a/config/test/test_config.global.php +++ b/config/test/test_config.global.php @@ -70,6 +70,8 @@ return [ 'process-name' => 'shlink_test', 'options' => [ 'pid_file' => sys_get_temp_dir() . '/shlink-test-swoole.pid', + 'worker_num' => 1, + 'task_worker_num' => 1, ], ], ], diff --git a/module/EventDispatcher/config/event_dispatcher.config.php b/module/EventDispatcher/config/event_dispatcher.config.php index 9930d9e3..336162b8 100644 --- a/module/EventDispatcher/config/event_dispatcher.config.php +++ b/module/EventDispatcher/config/event_dispatcher.config.php @@ -5,7 +5,6 @@ namespace Shlinkio\Shlink\EventDispatcher; use Phly\EventDispatcher as Phly; use Psr\EventDispatcher as Psr; -use Shlinkio\Shlink\Common; return [ diff --git a/module/EventDispatcher/src/Listener/ListenerProviderFactory.php b/module/EventDispatcher/src/Listener/ListenerProviderFactory.php index 7ad48508..1fb629f2 100644 --- a/module/EventDispatcher/src/Listener/ListenerProviderFactory.php +++ b/module/EventDispatcher/src/Listener/ListenerProviderFactory.php @@ -31,6 +31,10 @@ class ListenerProviderFactory implements FactoryInterface AttachableListenerProvider $provider, bool $isAsync = false ): void { + if (empty($events)) { + return; + } + // Avoid registering async event listeners when the swoole server is not registered if ($isAsync && ! $container->has(HttpServer::class)) { return; diff --git a/module/EventDispatcher/test/Listener/ListenerProviderFactoryTest.php b/module/EventDispatcher/test/Listener/ListenerProviderFactoryTest.php index 165bac37..f0c3b47f 100644 --- a/module/EventDispatcher/test/Listener/ListenerProviderFactoryTest.php +++ b/module/EventDispatcher/test/Listener/ListenerProviderFactoryTest.php @@ -8,8 +8,10 @@ use Phly\EventDispatcher\ListenerProvider\AttachableListenerProvider; use PHPUnit\Framework\TestCase; use ReflectionObject; use Shlinkio\Shlink\EventDispatcher\Listener\ListenerProviderFactory; +use Swoole\Http\Server as HttpServer; use function Phly\EventDispatcher\lazyListener; +use function Shlinkio\Shlink\EventDispatcher\asyncListener; class ListenerProviderFactoryTest extends TestCase { @@ -52,20 +54,22 @@ class ListenerProviderFactoryTest extends TestCase } /** @test */ - public function configuredEventsAreProperlyAttached(): void + public function configuredRegularEventsAreProperlyAttached(): void { $containerMock = $this->prophesize(ContainerInterface::class); $containerMock->has('config')->willReturn(true); $containerMock->get('config')->willReturn([ 'events' => [ - 'foo' => [ - 'bar', - 'baz', - ], - 'something' => [ - 'some_listener', - 'another_listener', - 'foobar', + 'regular' => [ + 'foo' => [ + 'bar', + 'baz', + ], + 'something' => [ + 'some_listener', + 'another_listener', + 'foobar', + ], ], ], ]); @@ -88,6 +92,79 @@ class ListenerProviderFactoryTest extends TestCase ], $listeners); } + /** @test */ + public function configuredAsyncEventsAreProperlyAttached(): void + { + $server = $this->createMock(HttpServer::class); // Some weird errors are thrown if prophesize is used + + $containerMock = $this->prophesize(ContainerInterface::class); + $containerMock->has('config')->willReturn(true); + $containerMock->get('config')->willReturn([ + 'events' => [ + 'async' => [ + 'foo' => [ + 'bar', + 'baz', + ], + 'something' => [ + 'some_listener', + 'another_listener', + 'foobar', + ], + ], + ], + ]); + $containerMock->has(HttpServer::class)->willReturn(true); + $containerMock->get(HttpServer::class)->willReturn($server); + $container = $containerMock->reveal(); + + $provider = ($this->factory)($container, ''); + $listeners = $this->getListenersFromProvider($provider); + + $this->assertInstanceOf(AttachableListenerProvider::class, $provider); + $this->assertEquals([ + 'foo' => [ + asyncListener($server, 'bar'), + asyncListener($server, 'baz'), + ], + 'something' => [ + asyncListener($server, 'some_listener'), + asyncListener($server, 'another_listener'), + asyncListener($server, 'foobar'), + ], + ], $listeners); + } + + /** @test */ + public function ignoresAsyncEventsWhenServerIsNotRegistered(): void + { + $containerMock = $this->prophesize(ContainerInterface::class); + $containerMock->has('config')->willReturn(true); + $containerMock->get('config')->willReturn([ + 'events' => [ + 'async' => [ + 'foo' => [ + 'bar', + 'baz', + ], + 'something' => [ + 'some_listener', + 'another_listener', + 'foobar', + ], + ], + ], + ]); + $containerMock->has(HttpServer::class)->willReturn(false); + $container = $containerMock->reveal(); + + $provider = ($this->factory)($container, ''); + $listeners = $this->getListenersFromProvider($provider); + + $this->assertInstanceOf(AttachableListenerProvider::class, $provider); + $this->assertEmpty($listeners); + } + private function getListenersFromProvider($provider): array { $ref = new ReflectionObject($provider);