From 2f679f192bc55f7b4cce4c82a879a5859821918e Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sun, 3 May 2026 19:11:47 +0300 Subject: [PATCH 1/5] Add `InMemoryAdapter` + Add stubs to CS Fixer config --- .php-cs-fixer.dist.php | 1 + .../InMemoryAdapter.php | 18 +++++++++++++++--- stubs/StubAdapter.php | 8 ++------ stubs/StubLoop.php | 3 +-- tests/Unit/QueueTest.php | 10 +++++----- 5 files changed, 24 insertions(+), 16 deletions(-) rename tests/App/MemoryAdapter.php => stubs/InMemoryAdapter.php (67%) diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 30655446..ad4f3336 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -9,6 +9,7 @@ $finder = (new Finder())->in([ __DIR__ . '/config', __DIR__ . '/src', + __DIR__ . '/stubs', __DIR__ . '/tests', ]); diff --git a/tests/App/MemoryAdapter.php b/stubs/InMemoryAdapter.php similarity index 67% rename from tests/App/MemoryAdapter.php rename to stubs/InMemoryAdapter.php index 53c1c5cc..917fa14b 100644 --- a/tests/App/MemoryAdapter.php +++ b/stubs/InMemoryAdapter.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yiisoft\Queue\Tests\App; +namespace Yiisoft\Queue\Stubs; use Yiisoft\Queue\Adapter\AdapterInterface; use Yiisoft\Queue\Message\IdEnvelope; @@ -11,9 +11,21 @@ use function count; -final class MemoryAdapter implements AdapterInterface +/** + * In-memory implementation of {@see AdapterInterface} for testing and development purposes. + * + * This adapter stores messages in a local array and processes them sequentially within the same process without any + * external queue backend. Messages are assigned incremental integer identifiers and are handled in FIFO order. + * + * Note: This implementation is not persistent and should not be used in production, as all data is lost when the + * process ends. + */ +final class InMemoryAdapter implements AdapterInterface { - /** @var array */ + /** + * @var MessageInterface[] + * @psalm-var array + */ private array $messages = []; private int $current = 0; diff --git a/stubs/StubAdapter.php b/stubs/StubAdapter.php index 6acbbac5..c2bcd293 100644 --- a/stubs/StubAdapter.php +++ b/stubs/StubAdapter.php @@ -13,9 +13,7 @@ */ final class StubAdapter implements AdapterInterface { - public function runExisting(callable $handlerCallback): void - { - } + public function runExisting(callable $handlerCallback): void {} public function status(int|string $id): MessageStatus { @@ -27,7 +25,5 @@ public function push(MessageInterface $message): MessageInterface return $message; } - public function subscribe(callable $handlerCallback): void - { - } + public function subscribe(callable $handlerCallback): void {} } diff --git a/stubs/StubLoop.php b/stubs/StubLoop.php index 20a238b5..414a4af7 100644 --- a/stubs/StubLoop.php +++ b/stubs/StubLoop.php @@ -13,8 +13,7 @@ final class StubLoop implements LoopInterface { public function __construct( private readonly bool $canContinue = true, - ) { - } + ) {} public function canContinue(): bool { diff --git a/tests/Unit/QueueTest.php b/tests/Unit/QueueTest.php index 2f9236f9..fa571f83 100644 --- a/tests/Unit/QueueTest.php +++ b/tests/Unit/QueueTest.php @@ -8,8 +8,8 @@ use Yiisoft\Queue\Message\IdEnvelope; use Yiisoft\Queue\Message\Message; use Yiisoft\Queue\MessageStatus; +use Yiisoft\Queue\Stubs\InMemoryAdapter; use Yiisoft\Queue\Tests\App\FakeAdapter; -use Yiisoft\Queue\Tests\App\MemoryAdapter; use Yiisoft\Queue\Tests\TestCase; use function extension_loaded; @@ -73,7 +73,7 @@ public function testStatusReturnsNotFoundWithoutAdapter(): void public function testRunWithAdapter(): void { - $queue = $this->createQueue(new MemoryAdapter()); + $queue = $this->createQueue(new InMemoryAdapter()); $message = new Message('simple', null); $queue->push($message); $queue->push(clone $message); @@ -84,7 +84,7 @@ public function testRunWithAdapter(): void public function testRunPartlyWithAdapter(): void { - $queue = $this->createQueue(new MemoryAdapter()); + $queue = $this->createQueue(new InMemoryAdapter()); $message = new Message('simple', null); $queue->push($message); $queue->push(clone $message); @@ -95,7 +95,7 @@ public function testRunPartlyWithAdapter(): void public function testListenWithAdapter(): void { - $queue = $this->createQueue(new MemoryAdapter()); + $queue = $this->createQueue(new InMemoryAdapter()); $message = new Message('simple', null); $queue->push($message); $queue->push(clone $message); @@ -107,7 +107,7 @@ public function testListenWithAdapter(): void public function testStatusWithAdapter(): void { - $queue = $this->createQueue(new MemoryAdapter()); + $queue = $this->createQueue(new InMemoryAdapter()); $envelope = $queue->push(new Message('simple', null)); self::assertArrayHasKey(IdEnvelope::MESSAGE_ID_KEY, $envelope->getMetadata()); From d998d665a3667dca7ed9d90e9d6e288ab0d447bd Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sun, 3 May 2026 20:03:35 +0300 Subject: [PATCH 2/5] tests --- stubs/StubAdapter.php | 29 --- .../Provider/QueueFactoryProviderTest.php | 5 +- tests/Unit/Stubs/InMemoryAdapterTest.php | 166 ++++++++++++++++++ tests/Unit/Stubs/StubAdapterTest.php | 25 --- 4 files changed, 168 insertions(+), 57 deletions(-) delete mode 100644 stubs/StubAdapter.php create mode 100644 tests/Unit/Stubs/InMemoryAdapterTest.php delete mode 100644 tests/Unit/Stubs/StubAdapterTest.php diff --git a/stubs/StubAdapter.php b/stubs/StubAdapter.php deleted file mode 100644 index c2bcd293..00000000 --- a/stubs/StubAdapter.php +++ /dev/null @@ -1,29 +0,0 @@ - $adapter, + AdapterInterface::class => new InMemoryAdapter(), ]); $provider = new QueueFactoryProvider( diff --git a/tests/Unit/Stubs/InMemoryAdapterTest.php b/tests/Unit/Stubs/InMemoryAdapterTest.php new file mode 100644 index 00000000..9a54131f --- /dev/null +++ b/tests/Unit/Stubs/InMemoryAdapterTest.php @@ -0,0 +1,166 @@ +push(new Message('test', 'a')); + $envelope2 = $adapter->push(new Message('test', 'b')); + $envelope3 = $adapter->push(new Message('test', 'c')); + + $this->assertInstanceOf(IdEnvelope::class, $envelope1); + $this->assertInstanceOf(IdEnvelope::class, $envelope2); + $this->assertInstanceOf(IdEnvelope::class, $envelope3); + + $this->assertSame(0, $envelope1->getId()); + $this->assertSame('a', $envelope1->getMessage()->getData()); + $this->assertSame(1, $envelope2->getId()); + $this->assertSame('b', $envelope2->getMessage()->getData()); + $this->assertSame(2, $envelope3->getId()); + $this->assertSame('c', $envelope3->getMessage()->getData()); + } + + public function testStatusWaitingForPushedMessage(): void + { + $adapter = new InMemoryAdapter(); + $envelope = $adapter->push(new Message('test', null)); + + $this->assertInstanceOf(IdEnvelope::class, $envelope); + $this->assertSame(MessageStatus::WAITING, $adapter->status($envelope->getId())); + } + + public function testStatusDoneAfterProcessing(): void + { + $adapter = new InMemoryAdapter(); + $envelope = $adapter->push(new Message('test', null)); + + $adapter->runExisting(static fn() => true); + + $this->assertInstanceOf(IdEnvelope::class, $envelope); + $this->assertSame(MessageStatus::DONE, $adapter->status($envelope->getId())); + } + + public function testStatusNotFoundForNonExistentId(): void + { + $adapter = new InMemoryAdapter(); + + $this->assertSame(MessageStatus::NOT_FOUND, $adapter->status(99)); + } + + public function testStatusNotFoundForNegativeId(): void + { + $adapter = new InMemoryAdapter(); + + $this->assertSame(MessageStatus::NOT_FOUND, $adapter->status(-1)); + } + + public function testStatusAcceptsStringId(): void + { + $adapter = new InMemoryAdapter(); + $envelope = $adapter->push(new Message('test', null)); + + $this->assertInstanceOf(IdEnvelope::class, $envelope); + $this->assertSame(MessageStatus::WAITING, $adapter->status((string) $envelope->getId())); + } + + public function testRunExistingProcessesAllMessages(): void + { + $adapter = new InMemoryAdapter(); + $adapter->push(new Message('test', 'a')); + $adapter->push(new Message('test', 'b')); + $adapter->push(new Message('test', 'c')); + + $processed = []; + $adapter->runExisting(static function (mixed $message) use (&$processed): bool { + $processed[] = $message->getData(); + return true; + }); + + $this->assertSame(['a', 'b', 'c'], $processed); + } + + public function testRunExistingStopsWhenHandlerReturnsFalse(): void + { + $adapter = new InMemoryAdapter(); + $adapter->push(new Message('test', 'a')); + $adapter->push(new Message('test', 'b')); + $adapter->push(new Message('test', 'c')); + + $processed = []; + $adapter->runExisting(static function (mixed $message) use (&$processed): bool { + $processed[] = $message->getData(); + return false; + }); + + $this->assertSame(['a'], $processed); + } + + public function testRunExistingOnEmptyQueue(): void + { + $adapter = new InMemoryAdapter(); + + $called = false; + $adapter->runExisting(static function () use (&$called): bool { + $called = true; + return true; + }); + + $this->assertFalse($called); + } + + public function testRunExistingDoesNotReprocessMessages(): void + { + $adapter = new InMemoryAdapter(); + $adapter->push(new Message('test', 'x')); + + $count = 0; + $handler = static function () use (&$count): bool { + $count++; + return true; + }; + $adapter->runExisting($handler); + $adapter->runExisting($handler); + + $this->assertSame(1, $count); + } + + public function testIdContinuesAfterProcessing(): void + { + $adapter = new InMemoryAdapter(); + $adapter->push(new Message('test', null)); + $adapter->runExisting(static fn() => true); + + $envelope = $adapter->push(new Message('test', null)); + + $this->assertInstanceOf(IdEnvelope::class, $envelope); + $this->assertSame(1, $envelope->getId()); + $this->assertSame(MessageStatus::WAITING, $adapter->status($envelope->getId())); + } + + public function testSubscribeProcessesExistingMessages(): void + { + $adapter = new InMemoryAdapter(); + $adapter->push(new Message('test', 'a')); + $adapter->push(new Message('test', 'b')); + + $processed = []; + $adapter->subscribe(static function (mixed $message) use (&$processed): bool { + $processed[] = $message->getData(); + return true; + }); + + $this->assertSame(['a', 'b'], $processed); + } +} diff --git a/tests/Unit/Stubs/StubAdapterTest.php b/tests/Unit/Stubs/StubAdapterTest.php deleted file mode 100644 index 8f455c6e..00000000 --- a/tests/Unit/Stubs/StubAdapterTest.php +++ /dev/null @@ -1,25 +0,0 @@ -assertSame($message, $adapter->push($message)); - $this->assertSame(MessageStatus::DONE, $adapter->status('test')); - $adapter->runExisting(static fn(MessageInterface $message): bool => true); - $adapter->subscribe(static fn(MessageInterface $message): bool => true); - } -} From aca9e917db608acf005c257d9d3c24d6532e4f24 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sun, 3 May 2026 21:45:13 +0300 Subject: [PATCH 3/5] fix psalm --- psalm.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/psalm.xml b/psalm.xml index 849e4c85..c3c1b590 100644 --- a/psalm.xml +++ b/psalm.xml @@ -12,16 +12,8 @@ - - - - - - - - From c772d0e65951f8573d732daced8e3c584a6895e2 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 5 May 2026 16:42:17 +0300 Subject: [PATCH 4/5] Improve tests --- tests/Unit/Stubs/InMemoryAdapterTest.php | 31 +++++++++++++++--------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/tests/Unit/Stubs/InMemoryAdapterTest.php b/tests/Unit/Stubs/InMemoryAdapterTest.php index 9a54131f..b38eb1d1 100644 --- a/tests/Unit/Stubs/InMemoryAdapterTest.php +++ b/tests/Unit/Stubs/InMemoryAdapterTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\TestCase; use Yiisoft\Queue\Message\IdEnvelope; use Yiisoft\Queue\Message\Message; +use Yiisoft\Queue\Message\MessageInterface; use Yiisoft\Queue\MessageStatus; use Yiisoft\Queue\Stubs\InMemoryAdapter; @@ -83,10 +84,12 @@ public function testRunExistingProcessesAllMessages(): void $adapter->push(new Message('test', 'c')); $processed = []; - $adapter->runExisting(static function (mixed $message) use (&$processed): bool { - $processed[] = $message->getData(); - return true; - }); + $adapter->runExisting( + static function (MessageInterface $message) use (&$processed): bool { + $processed[] = $message->getData(); + return true; + } + ); $this->assertSame(['a', 'b', 'c'], $processed); } @@ -99,10 +102,12 @@ public function testRunExistingStopsWhenHandlerReturnsFalse(): void $adapter->push(new Message('test', 'c')); $processed = []; - $adapter->runExisting(static function (mixed $message) use (&$processed): bool { - $processed[] = $message->getData(); - return false; - }); + $adapter->runExisting( + static function (MessageInterface $message) use (&$processed): bool { + $processed[] = $message->getData(); + return false; + } + ); $this->assertSame(['a'], $processed); } @@ -156,10 +161,12 @@ public function testSubscribeProcessesExistingMessages(): void $adapter->push(new Message('test', 'b')); $processed = []; - $adapter->subscribe(static function (mixed $message) use (&$processed): bool { - $processed[] = $message->getData(); - return true; - }); + $adapter->subscribe( + static function (MessageInterface $message) use (&$processed): bool { + $processed[] = $message->getData(); + return true; + } + ); $this->assertSame(['a', 'b'], $processed); } From 7d176c240c725a70cf4c025dc581d659c0984660 Mon Sep 17 00:00:00 2001 From: vjik <525501+vjik@users.noreply.github.com> Date: Tue, 5 May 2026 13:43:13 +0000 Subject: [PATCH 5/5] Apply PHP CS Fixer and Rector changes (CI) --- tests/Unit/Stubs/InMemoryAdapterTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Unit/Stubs/InMemoryAdapterTest.php b/tests/Unit/Stubs/InMemoryAdapterTest.php index b38eb1d1..a286e7db 100644 --- a/tests/Unit/Stubs/InMemoryAdapterTest.php +++ b/tests/Unit/Stubs/InMemoryAdapterTest.php @@ -88,7 +88,7 @@ public function testRunExistingProcessesAllMessages(): void static function (MessageInterface $message) use (&$processed): bool { $processed[] = $message->getData(); return true; - } + }, ); $this->assertSame(['a', 'b', 'c'], $processed); @@ -106,7 +106,7 @@ public function testRunExistingStopsWhenHandlerReturnsFalse(): void static function (MessageInterface $message) use (&$processed): bool { $processed[] = $message->getData(); return false; - } + }, ); $this->assertSame(['a'], $processed); @@ -165,7 +165,7 @@ public function testSubscribeProcessesExistingMessages(): void static function (MessageInterface $message) use (&$processed): bool { $processed[] = $message->getData(); return true; - } + }, ); $this->assertSame(['a', 'b'], $processed);