[Chapter9] WIP

This commit is contained in:
Carlos Buenosvinos
2022-03-07 15:12:28 +01:00
parent 7f4b80b6c9
commit 6559597db5
9 changed files with 150 additions and 7 deletions

View File

@@ -6,19 +6,21 @@ namespace Cheeper\Chapter7\Application\Author\Event;
use Cheeper\Chapter7\Application\Author\Projection\CreateFollowersCounterProjection;
use Cheeper\Chapter7\Application\Author\Projection\CreateFollowersCounterProjectionHandlerInterface;
use Cheeper\Chapter7\Application\Author\Projection\CreateTimelineProjection;
use Cheeper\Chapter7\Application\Author\Projection\CreateTimelineProjectionHandlerInterface;
use Cheeper\Chapter7\DomainModel\Author\NewAuthorSigned;
//snippet new-author-signed-event-handler
final class NewAuthorSignedEventHandler
{
public function __construct(
private CreateFollowersCounterProjectionHandlerInterface $projector
private CreateFollowersCounterProjectionHandlerInterface $followersProjector
) {
}
public function handle(NewAuthorSigned $event): void
{
$this->projector->__invoke(
$this->followersProjector->__invoke(
CreateFollowersCounterProjection::ofAuthor(
$event->authorId(),
$event->authorUsername()

View File

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Cheeper\Chapter7\Application\Author\Event;
use Cheeper\Chapter7\Application\Author\Projection\CreateFollowersCounterProjection;
use Cheeper\Chapter7\Application\Author\Projection\CreateFollowersCounterProjectionHandlerInterface;
use Cheeper\Chapter7\Application\Author\Projection\CreateTimelineProjection;
use Cheeper\Chapter7\Application\Author\Projection\CreateTimelineProjectionHandlerInterface;
use Cheeper\Chapter7\DomainModel\Author\NewAuthorSigned;
final class WhenNewAuthorSignedThenCreateTimelineProjectionEventHandler
{
public function __construct(
private CreateTimelineProjectionHandlerInterface $projector
) {
}
public function handle(NewAuthorSigned $event): void
{
$this->projector->__invoke(
CreateTimelineProjection::ofAuthor(
$event->authorId(),
$event->authorUsername()
)
);
}
}

View File

@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace Cheeper\Chapter7\Application\Author\Projection;
use Cheeper\Chapter7\Application\MessageTrait;
use Cheeper\Chapter7\Application\Projection;
final class CreateTimelineProjection implements Projection
{
use MessageTrait;
public static function ofAuthor(string $authorId, string $authorUsername): self
{
return new self($authorId, $authorUsername);
}
private function __construct(
private string $authorId,
private string $authorUsername
) {
$this->stampAsNewMessage();
}
public function authorId(): string
{
return $this->authorId;
}
public function authorUsername(): string
{
return $this->authorUsername;
}
}

View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace Cheeper\Chapter7\Application\Author\Projection;
use Cheeper\AllChapters\DomainModel\Author\AuthorId;
use Redis;
final class CreateTimelineProjectionHandler implements CreateTimelineProjectionHandlerInterface
{
public function __construct(
private Redis $redis
) {
}
public function __invoke(CreateTimelineProjection $projection): void
{
$authorId = AuthorId::fromString($projection->authorId());
$key = sprintf('author_timeline_projection:%s', $authorId);
$result = [
'id' => $projection->authorId(),
'username' => $projection->authorUsername(),
'followers' => 0,
];
$this->redis->set(
'author_followers_counter_projection:'.$authorId->toString(),
json_encode($result)
);
}
}
//end-snippet

View File

@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Cheeper\Chapter7\Application\Author\Projection;
interface CreateTimelineProjectionHandlerInterface
{
public function __invoke(CreateTimelineProjection $projection): void;
}

View File

@@ -18,7 +18,7 @@ final class TimelineQueryHandler
public function __invoke(TimelineQuery $query): TimelineQueryResponse
{
$authorId = $query->authorId();
$key = sprintf('timelines_%s', $authorId);
$key = sprintf('author_timeline_projection:%s', $authorId);
$this->checkAuthorExists($key, $authorId);

View File

@@ -25,7 +25,7 @@ final class SymfonyAuthorFollowedEventHandler implements MessageSubscriberInterf
{
yield AuthorFollowed::class => [
'method' => 'handle',
'from_transport' => 'chapter7_events',
'from_transport' => 'events_async',
];
}
}

View File

@@ -12,12 +12,13 @@ use Symfony\Component\Messenger\Handler\MessageSubscriberInterface;
final class SymfonyNewAuthorSignedEventHandler implements MessageSubscriberInterface
{
public function __construct(
private NewAuthorSignedEventHandler $eventHandler
private NewAuthorSignedEventHandler $eventHandler,
) {
}
public function handle(NewAuthorSigned $event): void
{
public function handle(
NewAuthorSigned $event
): void {
$this->eventHandler->handle($event);
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Cheeper\Chapter7\Infrastructure\Application\Author\Event;
use Cheeper\Chapter7\Application\Author\Event\WhenNewAuthorSignedThenCreateTimelineProjectionEventHandler;
use Cheeper\Chapter7\DomainModel\Author\NewAuthorSigned;
use Symfony\Component\Messenger\Handler\MessageSubscriberInterface;
final
class SymfonyWhenNewAuthorSignedThenCreateTimelineProjectionEventHandler
implements MessageSubscriberInterface
{
public function __construct(
private WhenNewAuthorSignedThenCreateTimelineProjectionEventHandler $eventHandler,
) {
}
public function handle(NewAuthorSigned $event): void
{
$this->eventHandler->handle($event);
}
public static function getHandledMessages(): iterable
{
yield NewAuthorSigned::class => [
'method' => 'handle',
'from_transport' => 'events_async',
];
}
}