Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to use backed enumerations as channel name #229

Merged
merged 7 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Adapter/AdapterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Queue\Adapter;

use BackedEnum;
use InvalidArgumentException;
use Yiisoft\Queue\Enum\JobStatus;
use Yiisoft\Queue\Message\MessageInterface;
Expand Down Expand Up @@ -40,7 +41,7 @@ public function push(MessageInterface $message): MessageInterface;
*/
public function subscribe(callable $handlerCallback): void;

public function withChannel(string $channel): self;
public function withChannel(string|BackedEnum $channel): self;

public function getChannelName(): string;
}
10 changes: 8 additions & 2 deletions src/Adapter/SynchronousAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Yiisoft\Queue\Adapter;

use BackedEnum;
use InvalidArgumentException;
use Yiisoft\Queue\ChannelNormalizer;
use Yiisoft\Queue\Enum\JobStatus;
use Yiisoft\Queue\Message\MessageInterface;
use Yiisoft\Queue\QueueInterface;
Expand All @@ -15,12 +17,14 @@ final class SynchronousAdapter implements AdapterInterface
{
private array $messages = [];
private int $current = 0;
private string $channel;

public function __construct(
private WorkerInterface $worker,
private QueueInterface $queue,
private string $channel = QueueInterface::DEFAULT_CHANNEL_NAME,
string|BackedEnum $channel = QueueInterface::DEFAULT_CHANNEL_NAME,
) {
$this->channel = ChannelNormalizer::normalize($channel);
}

public function __destruct()
Expand Down Expand Up @@ -74,8 +78,10 @@ public function subscribe(callable $handlerCallback): void
$this->runExisting($handlerCallback);
}

public function withChannel(string $channel): self
public function withChannel(string|BackedEnum $channel): self
{
$channel = ChannelNormalizer::normalize($channel);

if ($channel === $this->channel) {
return $this;
}
Expand Down
18 changes: 18 additions & 0 deletions src/ChannelNormalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Queue;

use BackedEnum;

/**
* @internal
*/
final class ChannelNormalizer
{
public static function normalize(string|BackedEnum $channel): string
{
return $channel instanceof BackedEnum ? (string) $channel->value : $channel;
}
}
5 changes: 3 additions & 2 deletions src/Debug/QueueProviderInterfaceProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Queue\Debug;

use BackedEnum;
use Yiisoft\Queue\Provider\QueueProviderInterface;
use Yiisoft\Queue\QueueInterface;

Expand All @@ -15,13 +16,13 @@ public function __construct(
) {
}

public function get(string $channel): QueueInterface
public function get(string|BackedEnum $channel): QueueInterface
{
$queue = $this->queueProvider->get($channel);
return new QueueDecorator($queue, $this->collector);
}

public function has(string $channel): bool
public function has(string|BackedEnum $channel): bool
{
return $this->queueProvider->has($channel);
}
Expand Down
10 changes: 8 additions & 2 deletions src/Provider/AdapterFactoryQueueProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

namespace Yiisoft\Queue\Provider;

use BackedEnum;
use Psr\Container\ContainerInterface;
use Yiisoft\Definitions\Exception\InvalidConfigException;
use Yiisoft\Factory\StrictFactory;
use Yiisoft\Queue\Adapter\AdapterInterface;
use Yiisoft\Queue\ChannelNormalizer;
use Yiisoft\Queue\QueueInterface;

use function array_key_exists;
Expand Down Expand Up @@ -50,17 +52,21 @@ public function __construct(
}
}

public function get(string $channel): QueueInterface
public function get(string|BackedEnum $channel): QueueInterface
{
$channel = ChannelNormalizer::normalize($channel);

$queue = $this->getOrTryToCreate($channel);
if ($queue === null) {
throw new ChannelNotFoundException($channel);
}

return $queue;
}

public function has(string $channel): bool
public function has(string|BackedEnum $channel): bool
{
$channel = ChannelNormalizer::normalize($channel);
return $this->factory->has($channel);
}

Expand Down
6 changes: 4 additions & 2 deletions src/Provider/ChannelNotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

namespace Yiisoft\Queue\Provider;

use BackedEnum;
use LogicException;
use Throwable;
use Yiisoft\Queue\ChannelNormalizer;

use function sprintf;

Expand All @@ -14,10 +16,10 @@
*/
final class ChannelNotFoundException extends LogicException implements QueueProviderException
{
public function __construct(string $channel, int $code = 0, ?Throwable $previous = null)
public function __construct(string|BackedEnum $channel, int $code = 0, ?Throwable $previous = null)
{
parent::__construct(
sprintf('Channel "%s" not found.', $channel),
sprintf('Channel "%s" not found.', ChannelNormalizer::normalize($channel)),
$code,
$previous,
);
Expand Down
5 changes: 3 additions & 2 deletions src/Provider/CompositeQueueProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Queue\Provider;

use BackedEnum;
use Yiisoft\Queue\QueueInterface;

/**
Expand All @@ -25,7 +26,7 @@ public function __construct(
$this->providers = $providers;
}

public function get(string $channel): QueueInterface
public function get(string|BackedEnum $channel): QueueInterface
{
foreach ($this->providers as $provider) {
if ($provider->has($channel)) {
Expand All @@ -35,7 +36,7 @@ public function get(string $channel): QueueInterface
throw new ChannelNotFoundException($channel);
}

public function has(string $channel): bool
public function has(string|BackedEnum $channel): bool
{
foreach ($this->providers as $provider) {
if ($provider->has($channel)) {
Expand Down
5 changes: 3 additions & 2 deletions src/Provider/PrototypeQueueProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Queue\Provider;

use BackedEnum;
use Yiisoft\Queue\Adapter\AdapterInterface;
use Yiisoft\Queue\QueueInterface;

Expand All @@ -22,12 +23,12 @@ public function __construct(
) {
}

public function get(string $channel): QueueInterface
public function get(string|BackedEnum $channel): QueueInterface
{
return $this->baseQueue->withAdapter($this->baseAdapter->withChannel($channel));
}

public function has(string $channel): bool
public function has(string|BackedEnum $channel): bool
{
return true;
}
Expand Down
9 changes: 5 additions & 4 deletions src/Provider/QueueProviderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Queue\Provider;

use BackedEnum;
use Yiisoft\Queue\QueueInterface;

/**
Expand All @@ -14,21 +15,21 @@ interface QueueProviderInterface
/**
* Find a queue by channel name and returns it.
*
* @param string $channel Channel name.
* @param BackedEnum|string $channel Channel name.
*
* @throws InvalidQueueConfigException If the queue configuration is invalid.
* @throws ChannelNotFoundException If the channel is not found.
* @throws QueueProviderException If the queue provider fails to provide a queue.
* @return QueueInterface Queue instance.
*/
public function get(string $channel): QueueInterface;
public function get(string|BackedEnum $channel): QueueInterface;

/**
* Check if a queue with the specified channel name exists.
*
* @param string $channel Channel name.
* @param BackedEnum|string $channel Channel name.
*
* @return bool Whether the queue exists.
*/
public function has(string $channel): bool;
public function has(string|BackedEnum $channel): bool;
}
15 changes: 10 additions & 5 deletions stubs/StubAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Yiisoft\Queue\Stubs;

use BackedEnum;
use Yiisoft\Queue\Adapter\AdapterInterface;
use Yiisoft\Queue\ChannelNormalizer;
use Yiisoft\Queue\Enum\JobStatus;
use Yiisoft\Queue\Message\MessageInterface;
use Yiisoft\Queue\QueueInterface;
Expand All @@ -14,8 +16,12 @@
*/
final class StubAdapter implements AdapterInterface
{
public function __construct(private string $channelName = QueueInterface::DEFAULT_CHANNEL_NAME)
{
private string $channelName;

public function __construct(
string|BackedEnum $channelName = QueueInterface::DEFAULT_CHANNEL_NAME
) {
$this->channelName = ChannelNormalizer::normalize($channelName);
}

public function runExisting(callable $handlerCallback): void
Expand All @@ -36,11 +42,10 @@ public function subscribe(callable $handlerCallback): void
{
}

public function withChannel(string $channel): AdapterInterface
public function withChannel(string|BackedEnum $channel): AdapterInterface
{
$new = clone $this;
$new->channelName = $channel;

$new->channelName = ChannelNormalizer::normalize($channel);
return $new;
}

Expand Down
7 changes: 4 additions & 3 deletions tests/App/FakeAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Yiisoft\Queue\Tests\App;

use BackedEnum;
use Yiisoft\Queue\Adapter\AdapterInterface;
use Yiisoft\Queue\ChannelNormalizer;
use Yiisoft\Queue\Enum\JobStatus;
use Yiisoft\Queue\Message\MessageInterface;

Expand Down Expand Up @@ -35,12 +37,11 @@ public function subscribe(callable $handlerCallback): void
//skip
}

public function withChannel(string $channel): AdapterInterface
public function withChannel(string|BackedEnum $channel): AdapterInterface
{
$instance = clone $this;
$instance->pushMessages = [];
$instance->channel = $channel;

$instance->channel = ChannelNormalizer::normalize($channel);
return $instance;
}

Expand Down
3 changes: 2 additions & 1 deletion tests/Benchmark/Support/VoidAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Queue\Tests\Benchmark\Support;

use BackedEnum;
use InvalidArgumentException;
use RuntimeException;
use Yiisoft\Queue\Adapter\AdapterInterface;
Expand Down Expand Up @@ -45,7 +46,7 @@ public function subscribe(callable $handlerCallback): void
throw new RuntimeException('Method is not implemented');
}

public function withChannel(string $channel): AdapterInterface
public function withChannel(string|BackedEnum $channel): AdapterInterface
{
throw new RuntimeException('Method is not implemented');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@

declare(strict_types=1);

namespace Yiisoft\Queue\Tests\Unit;
namespace Yiisoft\Queue\Tests\Unit\Adapter;

use PHPUnit\Framework\Attributes\DataProvider;
use Yiisoft\Queue\Adapter\SynchronousAdapter;
use Yiisoft\Queue\Enum\JobStatus;
use Yiisoft\Queue\Message\IdEnvelope;
use Yiisoft\Queue\Message\Message;
use Yiisoft\Queue\QueueInterface;
use Yiisoft\Queue\Stubs\StubQueue;
use Yiisoft\Queue\Stubs\StubWorker;
use Yiisoft\Queue\Tests\TestCase;
use Yiisoft\Queue\Message\IdEnvelope;
use Yiisoft\Queue\Tests\Unit\Support\IntEnum;
use Yiisoft\Queue\Tests\Unit\Support\StringEnum;

final class SynchronousAdapterTest extends TestCase
{
Expand Down Expand Up @@ -92,4 +98,27 @@ public function testStatusNotMessage(): void
$this->expectExceptionMessage('There is no message with the given ID.');
$adapter->status('1');
}

public static function dataChannels(): iterable
{
yield 'string' => ['test', 'test'];
yield 'string-enum' => ['red', StringEnum::RED];
yield 'integer-enum' => ['1', IntEnum::ONE];
}

#[DataProvider('dataChannels')]
public function testWithChannel(string $expected, mixed $channel): void
{
$adapter = (new SynchronousAdapter(new StubWorker(), new StubQueue()))->withChannel($channel);

$this->assertSame($expected, $adapter->getChannelName());
}

#[DataProvider('dataChannels')]
public function testChannelInConstructor(string $expected, mixed $channel): void
{
$adapter = new SynchronousAdapter(new StubWorker(), new StubQueue(), $channel);

$this->assertSame($expected, $adapter->getChannelName());
}
}
Loading
Loading