Skip to content

Commit

Permalink
Merge branch 'improve-domain-event-handling'
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusklocke committed Jan 14, 2022
2 parents 7448cc2 + 5c68ae6 commit b8b41fd
Show file tree
Hide file tree
Showing 61 changed files with 589 additions and 461 deletions.
53 changes: 47 additions & 6 deletions src/Application/Bus/BatchCommandBus.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

use HexagonalPlayground\Application\Handler\AuthAwareHandler;
use HexagonalPlayground\Application\OrmTransactionWrapperInterface;
use HexagonalPlayground\Application\Repository\EventRepositoryInterface;
use HexagonalPlayground\Application\Security\AuthChecker;
use HexagonalPlayground\Application\Security\AuthContext;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Log\LoggerInterface;

class BatchCommandBus
{
Expand All @@ -15,18 +18,38 @@ class BatchCommandBus
/** @var OrmTransactionWrapperInterface */
private $transactionWrapper;

/** @var EventDispatcherInterface */
private $eventDispatcher;

/** @var EventRepositoryInterface */
private $eventRepository;

/** @var AuthChecker */
private $authChecker;

/** @var LoggerInterface */
private $logger;

/**
* @param HandlerResolver $resolver
* @param OrmTransactionWrapperInterface $transactionWrapper
* @param EventDispatcherInterface $eventDispatcher
* @param EventRepositoryInterface $eventRepository
* @param LoggerInterface $logger
*/
public function __construct(HandlerResolver $resolver, OrmTransactionWrapperInterface $transactionWrapper)
{
public function __construct(
HandlerResolver $resolver,
OrmTransactionWrapperInterface $transactionWrapper,
EventDispatcherInterface $eventDispatcher,
EventRepositoryInterface $eventRepository,
LoggerInterface $logger
) {
$this->resolver = $resolver;
$this->transactionWrapper = $transactionWrapper;
$this->eventDispatcher = $eventDispatcher;
$this->eventRepository = $eventRepository;
$this->authChecker = new AuthChecker();
$this->logger = $logger;
}

/**
Expand All @@ -35,16 +58,34 @@ public function __construct(HandlerResolver $resolver, OrmTransactionWrapperInte
*/
public function execute(CommandQueue $commandQueue, ?AuthContext $authContext = null): void
{
$this->transactionWrapper->transactional(function () use ($commandQueue, $authContext) {
$events = $this->transactionWrapper->transactional(function () use ($commandQueue, $authContext) {
$events = [];

foreach ($commandQueue->getIterator() as $command) {
$handler = $this->resolver->resolve($command);
if ($handler instanceof AuthAwareHandler) {
$this->authChecker->check($authContext);
$handler($command, $authContext);
$events = array_merge($events, $handler($command, $authContext));
} else {
$handler($command);
$events = array_merge($events, $handler($command));
}
}

foreach ($events as $event) {
$this->eventRepository->save($event);
}

return $events;
});

foreach ($events as $event) {
$this->eventDispatcher->dispatch($event);
}

$this->logger->info('Successfully executed batch of commands.', [
'commands' => $commandQueue->size(),
'userId' => $authContext !== null ? $authContext->getUser()->getId() : null,
'events' => count($events)
]);
}
}
}
42 changes: 36 additions & 6 deletions src/Application/Bus/CommandBus.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
use HexagonalPlayground\Application\Command\CommandInterface;
use HexagonalPlayground\Application\Handler\AuthAwareHandler;
use HexagonalPlayground\Application\OrmTransactionWrapperInterface;
use HexagonalPlayground\Application\Repository\EventRepositoryInterface;
use HexagonalPlayground\Application\Security\AuthChecker;
use HexagonalPlayground\Application\Security\AuthContext;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Log\LoggerInterface;

class CommandBus
Expand All @@ -18,6 +20,12 @@ class CommandBus
/** @var OrmTransactionWrapperInterface */
private $transactionWrapper;

/** @var EventDispatcherInterface */
private $eventDispatcher;

/** @var EventRepositoryInterface */
private $eventRepository;

/** @var AuthChecker */
private $authChecker;

Expand All @@ -27,12 +35,21 @@ class CommandBus
/**
* @param HandlerResolver $resolver
* @param OrmTransactionWrapperInterface $transactionWrapper
* @param EventDispatcherInterface $eventDispatcher
* @param EventRepositoryInterface $eventRepository
* @param LoggerInterface $logger
*/
public function __construct(HandlerResolver $resolver, OrmTransactionWrapperInterface $transactionWrapper, LoggerInterface $logger)
{
public function __construct(
HandlerResolver $resolver,
OrmTransactionWrapperInterface $transactionWrapper,
EventDispatcherInterface $eventDispatcher,
EventRepositoryInterface $eventRepository,
LoggerInterface $logger
) {
$this->resolver = $resolver;
$this->transactionWrapper = $transactionWrapper;
$this->eventDispatcher = $eventDispatcher;
$this->eventRepository = $eventRepository;
$this->authChecker = new AuthChecker();
$this->logger = $logger;
}
Expand All @@ -44,17 +61,30 @@ public function __construct(HandlerResolver $resolver, OrmTransactionWrapperInte
public function execute(CommandInterface $command, ?AuthContext $authContext = null): void
{
$handler = $this->resolver->resolve($command);
$this->transactionWrapper->transactional(function() use ($handler, $command, $authContext) {

$events = $this->transactionWrapper->transactional(function() use ($handler, $command, $authContext) {
if ($handler instanceof AuthAwareHandler) {
$this->authChecker->check($authContext);
$handler($command, $authContext);
$events = $handler($command, $authContext);
} else {
$handler($command);
$events = $handler($command);
}

foreach ($events as $event) {
$this->eventRepository->save($event);
}

return $events;
});

foreach ($events as $event) {
$this->eventDispatcher->dispatch($event);
}

$this->logger->info('Successfully executed command.', [
'command' => get_class($command),
'userId' => $authContext !== null ? $authContext->getUser()->getId() : null
'userId' => $authContext !== null ? $authContext->getUser()->getId() : null,
'events' => count($events)
]);
}
}
5 changes: 5 additions & 0 deletions src/Application/Bus/CommandQueue.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ public function getIterator(): Iterator
{
return new ArrayIterator($this->commands);
}

public function size(): int
{
return count($this->commands);
}
}
28 changes: 0 additions & 28 deletions src/Application/EventStoreInterface.php

This file was deleted.

29 changes: 0 additions & 29 deletions src/Application/EventStoreSubscriber.php

This file was deleted.

32 changes: 25 additions & 7 deletions src/Application/Handler/AddRankingPenaltyHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use HexagonalPlayground\Application\Repository\SeasonRepositoryInterface;
use HexagonalPlayground\Application\Repository\TeamRepositoryInterface;
use HexagonalPlayground\Application\Security\AuthContext;
use HexagonalPlayground\Domain\Event\Event;
use HexagonalPlayground\Domain\RankingPenalty;
use HexagonalPlayground\Domain\Season;
use HexagonalPlayground\Domain\Team;

Expand All @@ -32,25 +34,41 @@ public function __construct(SeasonRepositoryInterface $seasonRepository, TeamRep
/**
* @param AddRankingPenaltyCommand $command
* @param AuthContext $authContext
* @return array|Event[]
*/
public function __invoke(AddRankingPenaltyCommand $command, AuthContext $authContext): void
public function __invoke(AddRankingPenaltyCommand $command, AuthContext $authContext): array
{
$events = [];

$isAdmin = new IsAdmin($authContext->getUser());
$isAdmin->check();

/** @var Season $season */
$season = $this->seasonRepository->find($command->getSeasonId());
$season = $this->seasonRepository->find($command->getSeasonId());
/** @var Team $team */
$team = $this->teamRepository->find($command->getTeamId());
$team = $this->teamRepository->find($command->getTeamId());
$ranking = $season->getRanking();

$season->getRanking()->addPenalty(
$penalty = new RankingPenalty(
$command->getId(),
$season->getRanking(),
$team,
$command->getReason(),
$command->getPoints(),
$authContext->getUser()
$command->getPoints()
);

$ranking->addPenalty($penalty);

$this->seasonRepository->save($season);

$events[] = new Event('ranking:penalty:added', [
'seasonId' => $season->getId(),
'teamId' => $team->getId(),
'reason' => $command->getReason(),
'points' => $command->getPoints(),
'userId' => $authContext->getUser()->getId()
]);

return $events;
}
}
}
6 changes: 5 additions & 1 deletion src/Application/Handler/AddTeamToSeasonHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use HexagonalPlayground\Application\Repository\SeasonRepositoryInterface;
use HexagonalPlayground\Application\Repository\TeamRepositoryInterface;
use HexagonalPlayground\Application\Security\AuthContext;
use HexagonalPlayground\Domain\Event\Event;
use HexagonalPlayground\Domain\Season;
use HexagonalPlayground\Domain\Team;

Expand All @@ -33,9 +34,10 @@ public function __construct(SeasonRepositoryInterface $seasonRepository, TeamRep
/**
* @param AddTeamToSeasonCommand $command
* @param AuthContext $authContext
* @return array|Event[]
* @throws NotFoundException
*/
public function __invoke(AddTeamToSeasonCommand $command, AuthContext $authContext): void
public function __invoke(AddTeamToSeasonCommand $command, AuthContext $authContext): array
{
$isAdmin = new IsAdmin($authContext->getUser());
$isAdmin->check();
Expand All @@ -46,5 +48,7 @@ public function __invoke(AddTeamToSeasonCommand $command, AuthContext $authConte
$team = $this->teamRepository->find($command->getTeamId());

$season->addTeam($team);

return [];
}
}
19 changes: 17 additions & 2 deletions src/Application/Handler/CancelMatchHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use HexagonalPlayground\Application\Permission\CanChangeMatch;
use HexagonalPlayground\Application\Repository\MatchRepositoryInterface;
use HexagonalPlayground\Application\Security\AuthContext;
use HexagonalPlayground\Domain\Event\Event;
use HexagonalPlayground\Domain\MatchEntity;

class CancelMatchHandler implements AuthAwareHandler
Expand All @@ -26,15 +27,29 @@ public function __construct(MatchRepositoryInterface $matchRepository)
/**
* @param CancelMatchCommand $command
* @param AuthContext $authContext
* @return array|Event[]
* @throws NotFoundException
*/
public function __invoke(CancelMatchCommand $command, AuthContext $authContext): void
public function __invoke(CancelMatchCommand $command, AuthContext $authContext): array
{
$events = [];

/** @var MatchEntity $match */
$match = $this->matchRepository->find($command->getMatchId());
$canChangeMatch = new CanChangeMatch($authContext->getUser(), $match);

$canChangeMatch = new CanChangeMatch($authContext->getUser(), $match);
$canChangeMatch->check();

$previousResult = $match->getMatchResult();
$match->cancel($command->getReason());

$events[] = new Event('match:cancelled', [
'id' => $match->getId(),
'reason' => $match->getCancellationReason(),
'homeScore' => $previousResult !== null ? $previousResult->getHomeScore() : null,
'guestScore' => $previousResult !== null ? $previousResult->getGuestScore() : null
]);

return $events;
}
}
8 changes: 6 additions & 2 deletions src/Application/Handler/ChangeUserPasswordHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@

use HexagonalPlayground\Application\Command\ChangeUserPasswordCommand;
use HexagonalPlayground\Application\Security\AuthContext;
use HexagonalPlayground\Domain\Event\Event;

class ChangeUserPasswordHandler implements AuthAwareHandler
{
/**
* @param ChangeUserPasswordCommand $command
* @param AuthContext $authContext
* @return array|Event[]
*/
public function __invoke(ChangeUserPasswordCommand $command, AuthContext $authContext): void
public function __invoke(ChangeUserPasswordCommand $command, AuthContext $authContext): array
{
$authContext->getUser()->setPassword($command->getNewPassword());

return [];
}
}
}
Loading

0 comments on commit b8b41fd

Please sign in to comment.