Skip to content
Closed
Show file tree
Hide file tree
Changes from 9 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
7 changes: 5 additions & 2 deletions .github/workflows/bechmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ name: bechmark

jobs:
phpbench:
uses: yiisoft/actions/.github/workflows/phpbench.yml@master
uses: yiisoft/actions/.github/workflows/phpbench.yml@phpbench-improvement
with:
os: >-
['ubuntu-latest', 'windows-latest']
php: >-
['8.1']
['8.1', '8.2', '8.3']
ref-name: master
secrets:
token: ${{ secrets.YIISOFT_GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"psr/container": "^1.0|^2.0",
"psr/log": "^2.0|^3.0",
"symfony/console": "^5.4|^6.0",
"yiisoft/arrays": "^3.1",
"yiisoft/definitions": "^1.0|^2.0|^3.0",
"yiisoft/friendly-exception": "^1.0",
"yiisoft/injector": "^1.0"
Expand Down
69 changes: 69 additions & 0 deletions src/Message/AbstractEnvelope.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Queue\Message;

use Yiisoft\Arrays\ArrayHelper;

abstract class AbstractEnvelope implements EnvelopeInterface
{
protected array $metadata = [];
private MessageInterface $message;

public function __construct(MessageInterface $message)
{
$this->metadata = $message->getMetadata();
$envelopes = [static::class];
while ($message instanceof EnvelopeInterface) {
if ($message::class !== static::class) {
$envelopes = [$message::class];
}

$message = $message->getMessage();
}
$this->message = $message;

if (isset($this->metadata[EnvelopeInterface::ENVELOPE_STACK_KEY]) && is_array($this->metadata[EnvelopeInterface::ENVELOPE_STACK_KEY])) {
$this->metadata[EnvelopeInterface::ENVELOPE_STACK_KEY] = array_merge(
$envelopes,
array_filter(
$this->metadata[EnvelopeInterface::ENVELOPE_STACK_KEY],
static fn (string $envelope): bool => !in_array($envelope, $envelopes),
),
);
} else {
$this->metadata[EnvelopeInterface::ENVELOPE_STACK_KEY] = [static::class];
}
}

public function getMessage(): MessageInterface
{
return $this->message;
}

public function getHandlerName(): string
{
return $this->message->getHandlerName();
}

public function getData(): mixed
{
return $this->message->getData();
}

public function getMetadata(): array
{
return ArrayHelper::merge(
$this->metadata,
$this->getEnvelopeMetadata(),
);
}

/**
* Metadata of the envelope
*
* @return array
*/
abstract protected function getEnvelopeMetadata(): array;
}
2 changes: 0 additions & 2 deletions src/Message/EnvelopeInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,4 @@ interface EnvelopeInterface extends MessageInterface
public static function fromMessage(MessageInterface $message): self;

public function getMessage(): MessageInterface;

public function withMessage(MessageInterface $message): self;
}
52 changes: 0 additions & 52 deletions src/Message/EnvelopeTrait.php

This file was deleted.

18 changes: 6 additions & 12 deletions src/Message/IdEnvelope.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,28 @@
/**
* ID envelope allows to identify a message.
*/
final class IdEnvelope implements EnvelopeInterface
final class IdEnvelope extends AbstractEnvelope
{
use EnvelopeTrait;

public const MESSAGE_ID_KEY = 'yii-message-id';

public function __construct(
private MessageInterface $message,
private string|int|null $id = null,
MessageInterface $message,
private readonly string|int|null $id = null,
) {
parent::__construct($message);
}

public static function fromMessage(MessageInterface $message): self
{
return new self($message, $message->getMetadata()[self::MESSAGE_ID_KEY] ?? null);
}

public function setId(string|int|null $id): void
{
$this->id = $id;
}

public function getId(): string|int|null
{
return $this->id ?? $this->message->getMetadata()[self::MESSAGE_ID_KEY] ?? null;
return $this->id ?? $this->metadata[self::MESSAGE_ID_KEY] ?? null;
}

private function getEnvelopeMetadata(): array
protected function getEnvelopeMetadata(): array
{
return [self::MESSAGE_ID_KEY => $this->getId()];
}
Expand Down
21 changes: 12 additions & 9 deletions src/Message/JsonMessageSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,24 @@ public function unserialize(string $value): MessageInterface
throw new InvalidArgumentException('Metadata must be array. Got ' . get_debug_type($meta) . '.');
}

$envelopes = [];
if (isset($meta[EnvelopeInterface::ENVELOPE_STACK_KEY]) && is_array($meta[EnvelopeInterface::ENVELOPE_STACK_KEY])) {
$envelopes = $meta[EnvelopeInterface::ENVELOPE_STACK_KEY];
}
$meta[EnvelopeInterface::ENVELOPE_STACK_KEY] = [];

// TODO: will be removed later
$message = new Message($payload['name'] ?? '$name', $payload['data'] ?? null, $meta);

if (isset($meta[EnvelopeInterface::ENVELOPE_STACK_KEY]) && is_array($meta[EnvelopeInterface::ENVELOPE_STACK_KEY])) {
$message = $message->withMetadata(
array_merge($message->getMetadata(), [EnvelopeInterface::ENVELOPE_STACK_KEY => []]),
);
foreach ($meta[EnvelopeInterface::ENVELOPE_STACK_KEY] as $envelope) {
if (is_string($envelope) && class_exists($envelope) && is_subclass_of($envelope, EnvelopeInterface::class)) {
$message = $envelope::fromMessage($message);
}
foreach ($envelopes as $envelope) {
if (is_string($envelope) && class_exists($envelope) && is_subclass_of(
$envelope,
EnvelopeInterface::class
)) {
$message = $envelope::fromMessage($message);
}
}


return $message;
}
}
10 changes: 1 addition & 9 deletions src/Message/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
final class Message implements MessageInterface
{
/**
* @param string $handlerName A name of a handler which should handle this message
* @param mixed $data Message data, encodable by a queue adapter
* @param array $metadata Message metadata, encodable by a queue adapter
* @param string|null $id Message id
*/
public function __construct(
private string $handlerName,
Expand All @@ -32,12 +32,4 @@ public function getMetadata(): array
{
return $this->metadata;
}

public function withMetadata(array $metadata): self
{
$instance = clone $this;
$instance->metadata = $metadata;

return $instance;
}
}
6 changes: 0 additions & 6 deletions src/Message/MessageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,16 @@ interface MessageInterface
{
/**
* Returns handler name.
*
* @return string
*/
public function getHandlerName(): string;

/**
* Returns payload data.
*
* @return mixed
*/
public function getData(): mixed;

/**
* Returns message metadata: timings, attempts count, metrics, etc.
*
* @return array
*/
public function getMetadata(): array;
}
20 changes: 8 additions & 12 deletions src/Middleware/FailureHandling/FailureEnvelope.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,28 @@

namespace Yiisoft\Queue\Middleware\FailureHandling;

use Yiisoft\Queue\Message\EnvelopeInterface;
use Yiisoft\Queue\Message\EnvelopeTrait;
use Yiisoft\Arrays\ArrayHelper;
use Yiisoft\Queue\Message\AbstractEnvelope;
use Yiisoft\Queue\Message\MessageInterface;

final class FailureEnvelope implements EnvelopeInterface
final class FailureEnvelope extends AbstractEnvelope
{
use EnvelopeTrait;

public const FAILURE_META_KEY = 'failure-meta';

public function __construct(
private MessageInterface $message,
private array $meta = [],
MessageInterface $message,
private readonly array $failureMeta = [],
) {
parent::__construct($message);
}

public static function fromMessage(MessageInterface $message): self
{
return new self($message, $message->getMetadata()[self::FAILURE_META_KEY] ?? []);
}

public function getMetadata(): array
protected function getEnvelopeMetadata(): array
{
$meta = $this->message->getMetadata();
$meta[self::FAILURE_META_KEY] = array_merge($meta[self::FAILURE_META_KEY] ?? [], $this->meta);

return $meta;
return [self::FAILURE_META_KEY => ArrayHelper::merge($this->metadata[self::FAILURE_META_KEY] ?? [], $this->failureMeta)];
}
}
6 changes: 1 addition & 5 deletions tests/Unit/EnvelopeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,7 @@ public function testEnvelopeDuplicates(): void

$stack = $message->getMetadata()[EnvelopeInterface::ENVELOPE_STACK_KEY];
$this->assertIsArray($stack);
$this->assertEquals([
IdEnvelope::class,
IdEnvelope::class,
IdEnvelope::class,
], $stack);
$this->assertEquals([IdEnvelope::class], $stack);

$this->assertEquals('test-id-3', $message->getMetadata()[IdEnvelope::MESSAGE_ID_KEY]);
}
Expand Down
7 changes: 5 additions & 2 deletions tests/Unit/Message/JsonMessageSerializerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function testUnserializeFromData(): void

$this->assertInstanceOf(MessageInterface::class, $message);
$this->assertEquals($payload['data'], $message->getData());
$this->assertEquals([], $message->getMetadata());
$this->assertEquals([EnvelopeInterface::ENVELOPE_STACK_KEY => []], $message->getMetadata());
}

public function testUnserializeWithMetadata(): void
Expand All @@ -78,7 +78,10 @@ public function testUnserializeWithMetadata(): void

$this->assertInstanceOf(MessageInterface::class, $message);
$this->assertEquals($payload['data'], $message->getData());
$this->assertEquals(['int' => 1, 'str' => 'string', 'bool' => true], $message->getMetadata());
$this->assertEquals(
['int' => 1, 'str' => 'string', 'bool' => true, EnvelopeInterface::ENVELOPE_STACK_KEY => []],
$message->getMetadata()
);
}

public function testUnserializeEnvelopeStack(): void
Expand Down
Loading
Loading