Skip to content

Commit

Permalink
[TransactionalMessenger] Refactoring, Added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fractalzombie committed Aug 21, 2022
1 parent 6af5e8e commit adf4d78
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 36 deletions.
35 changes: 16 additions & 19 deletions MessageBus/TransactionalMessageBus.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ public function dispatch(object $message, array $stamps = []): Envelope

TransactionHelper::isTransactional($message)
? $this->pendingStorage->append(new PendingEnvelope($envelope))
: $this->dispatchEnvelope($envelope)
;
: $this->dispatchEnvelope($envelope);

return $envelope;
}
Expand Down Expand Up @@ -85,26 +84,20 @@ public function rollback(\Throwable $exception): void
$this->dispatchFailedEnvelopes();
} catch (\Throwable $e) {
throw MessageBusException::fromThrowable($e);
} finally {
$this->pendingStorage->clear();
$this->succeedStorage->clear();
$this->failedStorage->clear();
}

$this->pendingStorage->clear();
$this->succeedStorage->clear();
$this->failedStorage->clear();
}

private function dispatchPendingEnvelopes(CommitType ...$commitTypes): void
{
$pendingEnvelopes = ArrayList::collect($this->pendingStorage->iterate());

$pendingEnvelopes
->filter(static fn (PendingEnvelope $pe) => TransactionHelper::isDispatchable($pe->getMessageClass(), ...$commitTypes))
->tap(fn (PendingEnvelope $pe) => $this->dispatchEnvelope($pe->envelope))
;

$pendingEnvelopes
->filter(static fn (PendingEnvelope $pe) => !TransactionHelper::isDispatchable($pe->getMessageClass(), ...$commitTypes))
->tap(fn (PendingEnvelope $pe) => $this->pendingStorage->prepend($pe))
;
ArrayList::collect($this->pendingStorage->iterate())->tap(
fn (PendingEnvelope $pe) => $pe->isTransactional(...$commitTypes)
? $this->dispatchEnvelope($pe->envelope)
: $this->pendingStorage->prepend($pe),
);
}

private function dispatchSucceedEnvelopes(): void
Expand All @@ -121,17 +114,21 @@ private function dispatchFailedEnvelopes(): void
;
}

private function dispatchEnvelope(Envelope $envelope): void
private function dispatchEnvelope(Envelope $envelope): Envelope
{
try {
$this->succeedStorage->append(new SucceedEnvelope($this->decoratedBus->dispatch($envelope)));
} catch (\Throwable $e) {
$this->failedStorage->append(new FailedEnvelope($envelope, $e));
} finally {
return $envelope;
}
}

private function dispatchEvent(Event $event): void
private function dispatchEvent(Event $event): Event
{
$this->eventDispatcher->dispatch($event);

return $event;
}
}
16 changes: 12 additions & 4 deletions Tests/Unit/MessageBus/TransactionalMessageBusCommitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,16 @@ public function testCommitMethod(
$this->eventDispatcher
->expects(self::exactly($expectsEventDispatcher))
->method('dispatch')
->willReturnCallback(fn (object $event) => self::assertInstanceOf($eventClass, $event))
->willThrowException(new \Exception('Something goes wrong'))
;

$this->expectException(MessageBusException::class);
} else {
$this->eventDispatcher
->expects(self::exactly($expectsEventDispatcher))
->method('dispatch')
->willThrowException(new \Exception('Something goes wrong'))
->willReturnCallback(fn (object $event) => self::assertInstanceOf($eventClass, $event))
;

$this->expectException(MessageBusException::class);
}

$envelope = $this->messageBus->dispatch($message);
Expand All @@ -99,6 +99,14 @@ public function testCommitMethod(
self::assertSame($failedCount, $this->failedStorage->count());
}

/** @throws \ReflectionException */
public function testPrivateDispatchEnvelopeMethod(): void
{
$envelope = EnvelopeHelper::wrap(new TransactionalOnTerminateMessage());

self::assertSame(spl_object_hash($envelope), spl_object_hash((new \ReflectionMethod($this->messageBus, 'dispatchEnvelope'))->invoke($this->messageBus, $envelope)));
}

public function dataProvider(): iterable
{
yield sprintf('%s is succeed commit', ClassHelper::getShortName(TransactionalOnTerminateMessage::class)) => [
Expand Down
36 changes: 30 additions & 6 deletions Tests/Unit/MessageBus/TransactionalMessageBusRollbackTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace FRZB\Component\TransactionalMessenger\Tests\Unit\MessageBus;

use FRZB\Component\TransactionalMessenger\Event\DispatchFailedEvent;
use FRZB\Component\TransactionalMessenger\Exception\MessageBusException;
use FRZB\Component\TransactionalMessenger\Helper\ClassHelper;
use FRZB\Component\TransactionalMessenger\Helper\EnvelopeHelper;
use FRZB\Component\TransactionalMessenger\MessageBus\TransactionalMessageBus as TransactionalMessageBusImpl;
Expand Down Expand Up @@ -50,19 +51,30 @@ public function testRollbackMethod(
int $pendingCount,
int $succeedCount,
int $failedCount,
int $expectsEventDispatcher
int $expectsEventDispatcher,
bool $isEventDispatcherThrows,
): void {
$this->decoratedBus
->expects(self::never())
->method('dispatch')
->willReturn(EnvelopeHelper::wrap($message))
;

$this->eventDispatcher
->expects(self::exactly($expectsEventDispatcher))
->method('dispatch')
->willReturnCallback(fn (DispatchFailedEvent $event) => self::assertSame(spl_object_hash($message), spl_object_hash($event->envelope->envelope->getMessage())))
;
if ($isEventDispatcherThrows) {
$this->eventDispatcher
->expects(self::exactly($expectsEventDispatcher))
->method('dispatch')
->willThrowException(new \Exception('Something goes wrong'))
;

$this->expectException(MessageBusException::class);
} else {
$this->eventDispatcher
->expects(self::exactly($expectsEventDispatcher))
->method('dispatch')
->willReturnCallback(fn (DispatchFailedEvent $event) => self::assertSame(spl_object_hash($message), spl_object_hash($event->envelope->envelope->getMessage())))
;
}

$envelope = $this->messageBus->dispatch($message);
$this->messageBus->rollback(new \Exception('Something goes wrong'));
Expand All @@ -81,6 +93,7 @@ public function dataProvider(): iterable
'succeed_count' => 0,
'failed_count' => 0,
'expects_event_dispatcher' => 1,
'is_event_dispatcher_throws' => false,
];

yield sprintf('%s is dispatched delayed', ClassHelper::getShortName(TransactionalOnResponseMessage::class)) => [
Expand All @@ -89,6 +102,7 @@ public function dataProvider(): iterable
'succeed_count' => 0,
'failed_count' => 0,
'expects_event_dispatcher' => 1,
'is_event_dispatcher_throws' => false,
];

yield sprintf('%s is dispatched delayed', ClassHelper::getShortName(TransactionalOnHandledMessage::class)) => [
Expand All @@ -97,6 +111,16 @@ public function dataProvider(): iterable
'succeed_count' => 0,
'failed_count' => 0,
'expects_event_dispatcher' => 1,
'is_event_dispatcher_throws' => false,
];

yield sprintf('%s event dispatcher throws', ClassHelper::getShortName(TransactionalOnHandledMessage::class)) => [
'message' => new TransactionalOnHandledMessage(),
'pending_count' => 0,
'succeed_count' => 0,
'failed_count' => 0,
'expects_event_dispatcher' => 1,
'is_event_dispatcher_throws' => true,
];
}
}
14 changes: 10 additions & 4 deletions Tests/Unit/ValueObject/PendingEnvelopeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace FRZB\Component\TransactionalMessenger\Tests\Unit\ValueObject;

use FRZB\Component\TransactionalMessenger\Enum\CommitType;
use FRZB\Component\TransactionalMessenger\Helper\EnvelopeHelper;
use FRZB\Component\TransactionalMessenger\Tests\Stub\Message\TransactionalOnHandledMessage;
use FRZB\Component\TransactionalMessenger\Tests\Stub\Message\TransactionalOnResponseMessage;
Expand All @@ -18,28 +19,33 @@
class PendingEnvelopeTest extends TestCase
{
#[DataProvider('dataProvider')]
public function testConstructorMethod(object $message): void
public function testConstructorMethod(object $message, array $commitTypes): void
{
$envelope = EnvelopeHelper::wrap($message);
$whenPended = new \DateTimeImmutable();
$failedEnvelope = new PendingEnvelope($envelope, $whenPended);
$pendingEnvelope = new PendingEnvelope($envelope, $whenPended);

self::assertSame($whenPended, $failedEnvelope->whenPended);
self::assertSame(spl_object_hash($message), spl_object_hash($failedEnvelope->envelope->getMessage()));
self::assertSame($whenPended, $pendingEnvelope->whenPended);
self::assertSame(spl_object_hash($message), spl_object_hash($pendingEnvelope->envelope->getMessage()));
self::assertSame($message::class, $pendingEnvelope->getMessageClass());
self::assertTrue($pendingEnvelope->isTransactional(...$commitTypes));
}

public function dataProvider(): iterable
{
yield 'TransactionalOnTerminateMessage with PendingEnvelope' => [
'message' => new TransactionalOnTerminateMessage(),
'commitTypes' => [CommitType::OnTerminate],
];

yield 'TransactionalOnResponseMessage with PendingEnvelope' => [
'message' => new TransactionalOnResponseMessage(),
'commitTypes' => [CommitType::OnResponse],
];

yield 'TransactionalOnHandledMessage with PendingEnvelope' => [
'message' => new TransactionalOnHandledMessage(),
'commitTypes' => [CommitType::OnHandled],
];
}
}
6 changes: 3 additions & 3 deletions Tests/Unit/ValueObject/SucceedEnvelopeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ public function testConstructorMethod(object $message): void
{
$envelope = EnvelopeHelper::wrap($message);
$whenDispatched = new \DateTimeImmutable();
$failedEnvelope = new SucceedEnvelope($envelope, $whenDispatched);
$succeedEnvelope = new SucceedEnvelope($envelope, $whenDispatched);

self::assertSame($whenDispatched, $failedEnvelope->whenDispatched);
self::assertSame(spl_object_hash($message), spl_object_hash($failedEnvelope->envelope->getMessage()));
self::assertSame($whenDispatched, $succeedEnvelope->whenDispatched);
self::assertSame(spl_object_hash($message), spl_object_hash($succeedEnvelope->envelope->getMessage()));
}

public function dataProvider(): iterable
Expand Down
7 changes: 7 additions & 0 deletions ValueObject/PendingEnvelope.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace FRZB\Component\TransactionalMessenger\ValueObject;

use FRZB\Component\TransactionalMessenger\Enum\CommitType;
use FRZB\Component\TransactionalMessenger\Helper\TransactionHelper;
use JetBrains\PhpStorm\Immutable;
use Symfony\Component\Messenger\Envelope;

Expand All @@ -21,4 +23,9 @@ public function getMessageClass(): string
{
return $this->envelope->getMessage()::class;
}

public function isTransactional(CommitType ...$commitTypes): bool
{
return TransactionHelper::isDispatchable($this->getMessageClass(), ...$commitTypes);
}
}

0 comments on commit adf4d78

Please sign in to comment.