Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 6 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@
"yiisoft/injector": "^1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.93",
"friendsofphp/php-cs-fixer": "^3.95.11",
"maglnet/composer-require-checker": "^4.7.1",
"phpbench/phpbench": "^1.4.1",
"phpunit/phpunit": "^10.5.45",
"rector/rector": "^2.0.11",
"phpbench/phpbench": "^1.4.3",
"phpunit/phpunit": "^10.5.63",
"rector/rector": "^2.5.2",
"roave/infection-static-analysis-plugin": "^1.35",
"vimeo/psalm": "^5.26.1 || ^6.10",
"vimeo/psalm": "^5.26.1 || ^6.16.1",
"yiisoft/code-style": "^1.0",
"yiisoft/test-support": "^3.0.2",
"yiisoft/test-support": "^3.2.0",
"yiisoft/yii-debug": "dev-master"
},
"suggest": {
Expand Down
2 changes: 1 addition & 1 deletion psalm.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<psalm
errorLevel="2"
errorLevel="1"
findUnusedBaselineEntry="true"
findUnusedCode="false"
ensureOverrideAttribute="false"
Expand Down
12 changes: 0 additions & 12 deletions src/Cli/SignalLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,8 @@
{
use SoftLimitTrait;

/**
* @psalm-suppress UndefinedConstant
* @psalm-suppress MissingClassConstType
*/
protected const SIGNALS_EXIT = [SIGHUP, SIGINT, SIGTERM];
/**
* @psalm-suppress UndefinedConstant
* @psalm-suppress MissingClassConstType
*/
protected const SIGNALS_SUSPEND = [SIGTSTP];
/**
* @psalm-suppress UndefinedConstant
* @psalm-suppress MissingClassConstType
*/
protected const SIGNALS_RESUME = [SIGCONT];
protected bool $pause = false;
protected bool $exit = false;
Expand All @@ -36,7 +24,7 @@
* @param int $memorySoftLimit Soft RAM limit in bytes. The loop won't let you continue to execute the program if
* soft limit is reached. Zero means no limit.
*/
public function __construct(protected int $memorySoftLimit = 0)

Check warning on line 27 in src/Cli/SignalLoop.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.5-ubuntu-latest

Escaped Mutant for Mutator "IncrementInteger": @@ @@ * @param int $memorySoftLimit Soft RAM limit in bytes. The loop won't let you continue to execute the program if * soft limit is reached. Zero means no limit. */ - public function __construct(protected int $memorySoftLimit = 0) + public function __construct(protected int $memorySoftLimit = 1) { foreach (self::SIGNALS_EXIT as $signal) { pcntl_signal($signal, fn() => $this->exit = true);

Check warning on line 27 in src/Cli/SignalLoop.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.5-ubuntu-latest

Escaped Mutant for Mutator "DecrementInteger": @@ @@ * @param int $memorySoftLimit Soft RAM limit in bytes. The loop won't let you continue to execute the program if * soft limit is reached. Zero means no limit. */ - public function __construct(protected int $memorySoftLimit = 0) + public function __construct(protected int $memorySoftLimit = -1) { foreach (self::SIGNALS_EXIT as $signal) { pcntl_signal($signal, fn() => $this->exit = true);
{
foreach (self::SIGNALS_EXIT as $signal) {
pcntl_signal($signal, fn() => $this->exit = true);
Expand Down Expand Up @@ -65,12 +53,12 @@

protected function dispatchSignals(): bool
{
pcntl_signal_dispatch();

Check warning on line 56 in src/Cli/SignalLoop.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.5-ubuntu-latest

Escaped Mutant for Mutator "FunctionCallRemoval": @@ @@ protected function dispatchSignals(): bool { - pcntl_signal_dispatch(); + // Wait for resume signal until the loop is suspended while ($this->pause && !$this->exit) {

// Wait for resume signal until the loop is suspended
while ($this->pause && !$this->exit) {
usleep(10000);

Check warning on line 60 in src/Cli/SignalLoop.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.5-ubuntu-latest

Escaped Mutant for Mutator "FunctionCallRemoval": @@ @@ // Wait for resume signal until the loop is suspended while ($this->pause && !$this->exit) { - usleep(10000); + pcntl_signal_dispatch(); }

Check warning on line 60 in src/Cli/SignalLoop.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.5-ubuntu-latest

Escaped Mutant for Mutator "IncrementInteger": @@ @@ // Wait for resume signal until the loop is suspended while ($this->pause && !$this->exit) { - usleep(10000); + usleep(10001); pcntl_signal_dispatch(); }

Check warning on line 60 in src/Cli/SignalLoop.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.5-ubuntu-latest

Escaped Mutant for Mutator "DecrementInteger": @@ @@ // Wait for resume signal until the loop is suspended while ($this->pause && !$this->exit) { - usleep(10000); + usleep(9999); pcntl_signal_dispatch(); }
pcntl_signal_dispatch();

Check warning on line 61 in src/Cli/SignalLoop.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.5-ubuntu-latest

Escaped Mutant for Mutator "FunctionCallRemoval": @@ @@ // Wait for resume signal until the loop is suspended while ($this->pause && !$this->exit) { usleep(10000); - pcntl_signal_dispatch(); + } return !$this->exit;
}

return !$this->exit;
Expand Down
8 changes: 4 additions & 4 deletions src/Command/ListenCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ public function configure(): void

protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->queueProvider
->get($input->getArgument('queue'))
->listen();
$queueName = (string) $input->getArgument('queue');

return 0;
$this->queueProvider->get($queueName)->listen();

return Command::SUCCESS;
}
}
21 changes: 19 additions & 2 deletions src/Debug/QueueCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@ final class QueueCollector implements SummaryCollectorInterface
{
use CollectorTrait;

/**
* @var array[]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it obvious that it is an array?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's array of arrays, not just array.

*/
private array $pushes = [];
private array $statuses = [];

/**
* @var array[]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it obvious that it is an array?

*/
private array $processingMessages = [];

public function getCollected(): array
Expand Down Expand Up @@ -72,9 +79,19 @@ public function getSummary(): array
return [];
}

$countPushes = array_sum(array_map(static fn($messages) => is_countable($messages) ? count($messages) : 0, $this->pushes));
$countPushes = array_sum(
array_map(
count(...),
$this->pushes,
),
);
$countStatuses = count($this->statuses);
$countProcessingMessages = array_sum(array_map(static fn($messages) => is_countable($messages) ? count($messages) : 0, $this->processingMessages));
$countProcessingMessages = array_sum(
array_map(
count(...),
$this->processingMessages,
),
);

return [
'countPushes' => $countPushes,
Expand Down
2 changes: 1 addition & 1 deletion src/Message/GenericMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function __construct(
private readonly bool|int|float|string|array|null $payload,
) {}

public static function fromPayload(string $type, bool|int|float|string|array|null $payload): MessageInterface
public static function fromPayload(string $type, bool|int|float|string|array|null $payload): static
{
return new self($type, $payload);
}
Expand Down
7 changes: 6 additions & 1 deletion src/Message/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@

namespace Yiisoft\Queue\Message;

/**
* Base implementation of {@see MessageInterface} providing metadata storage.
*
* @psalm-import-type MessageMeta from MessageInterface
*/
abstract class Message implements MessageInterface
{
/**
* @psalm-var array<string, mixed>
* @psalm-var MessageMeta
*/
private array $meta = [];

Expand Down
6 changes: 5 additions & 1 deletion src/Message/MessageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ interface MessageInterface
* `int`, `float`, `string`), or arrays composed of the same types recursively.
*
* @psalm-param MessagePayload $payload
*
* @return static Instance of the called class with the given type and payload.
*/
public static function fromPayload(string $type, bool|int|float|string|array|null $payload): self;
public static function fromPayload(string $type, bool|int|float|string|array|null $payload): static;

/**
* Returns message type.
Expand Down Expand Up @@ -56,6 +58,8 @@ public function getMeta(): array;
* @param array<string, bool|int|float|string|array|null> $meta Metadata containing only `null`, scalars (`bool`,
* `int`, `float`, `string`), or arrays composed of the same types recursively.
*
* @return static New instance with the given metadata.
*
* @psalm-param MessageMeta $meta
*/
public function withMeta(array $meta): static;
Expand Down
5 changes: 4 additions & 1 deletion src/Message/Serializer/MessageEncoderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ interface MessageEncoderInterface
/**
* Encodes a data array into a string representation.
*
* @param array $data Data to encode. Contains only scalars, nulls, and arrays — no objects or resources including array contents.
* @param array $data Data to encode. Contains only scalars, nulls, and arrays — no objects or resources including
* array contents.
*
* @return string Encoded string.
*
* @throws MessageSerializerException If encoding fails.
*/
Expand Down
9 changes: 8 additions & 1 deletion src/Message/Serializer/MessageSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
* {@see MessageEncoderInterface}, which encodes it to a string. When unserializing, decodes the string back to an
* array and resolves the message class from the type via the resolver, falling back to {@see GenericMessage}
* if the type is not registered.
*
* @psalm-import-type MessagePayload from MessageInterface
* @psalm-import-type MessageMeta from MessageInterface
*/
final class MessageSerializer implements MessageSerializerInterface
{
Expand Down Expand Up @@ -66,9 +69,13 @@ public function unserialize(string $value): MessageInterface
if (!is_array($meta)) {
throw new MessageSerializerException('Metadata must be an array. Got ' . get_debug_type($meta) . '.');
}
/** @psalm-var MessageMeta $meta */

$class = $this->resolver->resolve($type) ?? GenericMessage::class;

return $class::fromPayload($type, $data['payload'] ?? null)->withMeta($meta);
/** @psalm-var MessagePayload $payload */
$payload = $data['payload'] ?? null;

return $class::fromPayload($type, $payload)->withMeta($meta);
}
}
3 changes: 2 additions & 1 deletion src/Middleware/CallableFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,15 @@ public function create(mixed $definition): callable
&& array_keys($definition) === [0, 1]
&& is_string($definition[1])
) {
/** @psalm-var array{0:mixed,1:string} $definition */

if (is_object($definition[0])) {
$callable = $this->fromObjectDefinition($definition[0], $definition[1]);
if ($callable !== null) {
return $callable;
}
}

/** @psalm-suppress PossiblyUndefinedArrayOffset array_keys($definition) === [0, 1] was checked above */
if (is_string($definition[0])) {
$callable = $this->fromDefinition($definition[0], $definition[1]);
if ($callable !== null) {
Expand Down
2 changes: 1 addition & 1 deletion src/Middleware/Consume/ConsumeMiddlewareDispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public function hasMiddlewares(): bool
}

/**
* @return Closure[]
* @psalm-return list<Closure():ConsumeMiddlewareInterface>
*/
private function buildMiddlewares(): array
{
Expand Down
17 changes: 10 additions & 7 deletions src/Middleware/Consume/ConsumeMiddlewareStack.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ final class ConsumeMiddlewareStack implements ConsumeHandlerInterface
* @param Closure[] $middlewares Middlewares.
* @param ConsumeHandlerInterface $finishHandler Fallback handler
* events.
*
* @psalm-param list<Closure():ConsumeMiddlewareInterface> $middlewares
*/
public function __construct(
private readonly array $middlewares,
Expand All @@ -28,33 +30,34 @@ public function __construct(

public function handleConsume(ConsumeRequest $request): ConsumeRequest
{
if ($this->stack === null) {
$this->build();
}

/** @psalm-suppress PossiblyNullReference */
$this->stack ??= $this->build();
return $this->stack->handleConsume($request);
}

private function build(): void
private function build(): ConsumeHandlerInterface
{
$handler = $this->finishHandler;

foreach ($this->middlewares as $middleware) {
$handler = $this->wrap($middleware, $handler);
}

$this->stack = $handler;
return $handler;
}

/**
* Wrap handler by middlewares.
*
* @psalm-param Closure():ConsumeMiddlewareInterface $middlewareFactory
*/
private function wrap(Closure $middlewareFactory, ConsumeHandlerInterface $handler): ConsumeHandlerInterface
{
return new class ($middlewareFactory, $handler) implements ConsumeHandlerInterface {
private ?ConsumeMiddlewareInterface $middleware = null;

/**
* @psalm-param Closure():ConsumeMiddlewareInterface $middlewareFactory
*/
public function __construct(
private readonly Closure $middlewareFactory,
private readonly ConsumeHandlerInterface $handler,
Expand Down
11 changes: 10 additions & 1 deletion src/Middleware/FailureHandling/FailureEnvelope.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,24 @@
use function is_array;

/**
* @psalm-type FailureMeta = array<string, scalar|null|array<scalar|null|array>>
* @extends Envelope<array{
* yii-failure: array<string, scalar|null|array<scalar|null|array>>,
* yii-failure: FailureMeta,
* ...<string, scalar|null|array<scalar|null|array>>
* }>
*/
final class FailureEnvelope extends Envelope
{
public const META_FAILURE = 'yii-failure';

/**
* @psalm-var FailureMeta
*/
private array $failureMeta;

public function __construct(MessageInterface $message, array $failureMeta = [])
{
/** @psalm-var FailureMeta */
$this->failureMeta = $failureMeta === []
? self::getFailureMetaFromMessage($message)
: ArrayHelper::merge(
Expand Down Expand Up @@ -54,11 +59,15 @@ public static function fromMessage(MessageInterface $message): static
);
}

/**
* @psalm-return FailureMeta
*/
private static function getFailureMetaFromMessage(MessageInterface $message): array
{
$meta = $message->getMeta();
if (array_key_exists(self::META_FAILURE, $meta)) {
$result = $meta[self::META_FAILURE];
/** @psalm-var FailureMeta */
return is_array($result) ? $result : [];
}
return [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private function init(): void
}

/**
* @return Closure[]
* @psalm-return list<Closure():FailureMiddlewareInterface>
*/
private function buildMiddlewares(array|callable|string|FailureMiddlewareInterface ...$definitions): array
{
Expand Down
16 changes: 9 additions & 7 deletions src/Middleware/FailureHandling/FailureMiddlewareStack.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ final class FailureMiddlewareStack implements FailureHandlerInterface
* @param Closure[] $middlewares Middlewares.
* @param FailureHandlerInterface $finishHandler Fallback handler
* events.
*
* @psalm-param list<Closure():FailureMiddlewareInterface> $middlewares
*/
public function __construct(
private readonly array $middlewares,
Expand All @@ -28,33 +30,33 @@ public function __construct(

public function handleFailure(FailureHandlingRequest $request): FailureHandlingRequest
{
if ($this->stack === null) {
$this->build();
}

/** @psalm-suppress PossiblyNullReference */
$this->stack ??= $this->build();
return $this->stack->handleFailure($request);
}

private function build(): void
private function build(): FailureHandlerInterface
{
$handler = $this->finishHandler;

foreach ($this->middlewares as $middleware) {
$handler = $this->wrap($middleware, $handler);
}

$this->stack = $handler;
return $handler;
}

/**
* Wrap handler by middlewares.
* @psalm-param Closure():FailureMiddlewareInterface $middlewareFactory
*/
private function wrap(Closure $middlewareFactory, FailureHandlerInterface $handler): FailureHandlerInterface
{
return new class ($middlewareFactory, $handler) implements FailureHandlerInterface {
private ?FailureMiddlewareInterface $middleware = null;

/**
* @psalm-param Closure():FailureMiddlewareInterface $middlewareFactory
*/
public function __construct(
private readonly Closure $middlewareFactory,
private readonly FailureHandlerInterface $handler,
Expand Down
5 changes: 1 addition & 4 deletions src/Middleware/InvalidMiddlewareDefinitionException.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@

final class InvalidMiddlewareDefinitionException extends InvalidArgumentException
{
/**
* @param array|callable|string $middlewareDefinition
*/
public function __construct($middlewareDefinition, int $code = 0, ?Throwable $previous = null)
public function __construct(mixed $middlewareDefinition, int $code = 0, ?Throwable $previous = null)
{
$message = 'Parameter should be either middleware class name or a callable.';

Expand Down
Loading
Loading