[Chapter 9 - Demo] Finishing all the demo with all the snapshots of the infra
This commit is contained in:
15
README.md
15
README.md
@@ -1,3 +1,5 @@
|
||||
# Cheeper: CQRS By Example Repository
|
||||
|
||||
<h1 align="center">
|
||||
<a href="http://leanpub.com/cqrs-by-example">
|
||||
<img src="http://gitmood.app/assets/images/cheeper.svg" width="150" alt="cheeper logo">
|
||||
@@ -26,25 +28,16 @@
|
||||
|
||||
This code can run fully on docker. In order to do so just run
|
||||
|
||||
make run
|
||||
make start
|
||||
|
||||
To start the development environment. If this is the first time you run the code you will need to run database migrations
|
||||
|
||||
make database
|
||||
make infrastructure
|
||||
|
||||
And to stop all services just run
|
||||
|
||||
make stop
|
||||
|
||||
### Local Symfony Webserver + Docker for external services
|
||||
|
||||
This code can also be run using Symfony Local Webserver.
|
||||
|
||||
### Fixtures
|
||||
|
||||
make database
|
||||
|
||||
|
||||
Cheeper starts totally as a blank application. There is no Author, Cheeps, Follows, etc. Let's see what happens with the existing Projections when
|
||||
|
||||
#### Follower Counters Query
|
||||
|
||||
@@ -37,8 +37,8 @@ final class FollowAuthorController extends AbstractController
|
||||
$httpContent['data']['from_author_id'] = $command->fromAuthorId();
|
||||
$httpContent['data']['to_author_id'] = $command->toAuthorId();
|
||||
} catch (
|
||||
AuthorDoesNotExist
|
||||
|InvalidArgumentException $exception
|
||||
AuthorDoesNotExist
|
||||
|InvalidArgumentException $exception
|
||||
) {
|
||||
$httpCode = Response::HTTP_INTERNAL_SERVER_ERROR;
|
||||
$httpContent['data']['message'] = $exception->getMessage();
|
||||
|
||||
@@ -13,7 +13,6 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
//snippet chapter7-postcheep-controller
|
||||
@@ -23,32 +22,35 @@ final class PostCheepController extends AbstractController
|
||||
public function __invoke(Request $request, CommandBus $commandBus): Response
|
||||
{
|
||||
$httpCode = Response::HTTP_ACCEPTED;
|
||||
$httpContent = [
|
||||
'meta' => [],
|
||||
'data' => [],
|
||||
];
|
||||
|
||||
$command = null;
|
||||
try {
|
||||
$command = PostCheepCommand::fromArray(
|
||||
$this->getRequestContentInJson($request)
|
||||
);
|
||||
|
||||
$commandBus->handle($command);
|
||||
$httpContent = [
|
||||
'message_id' => $command->messageId()?->toString(),
|
||||
'cheep_id' => $command->authorId(),
|
||||
];
|
||||
|
||||
return $this->buildJsonResponse(
|
||||
$httpContent,
|
||||
$httpCode
|
||||
);
|
||||
$httpContent['data']['cheep_id'] = $command->cheepId();
|
||||
|
||||
} catch (
|
||||
AuthorDoesNotExist
|
||||
| InvalidArgumentException $exception
|
||||
) {
|
||||
throw new HttpException(
|
||||
statusCode: Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
message: $exception->getMessage(),
|
||||
previous: $exception
|
||||
);
|
||||
$httpCode = Response::HTTP_INTERNAL_SERVER_ERROR;
|
||||
$httpContent['data']['message'] = $exception->getMessage();
|
||||
} finally {
|
||||
$httpContent['meta']['message_id'] = $command?->messageId()?->toString();
|
||||
}
|
||||
|
||||
return $this->buildJsonResponse(
|
||||
$httpContent,
|
||||
$httpCode
|
||||
);
|
||||
}
|
||||
|
||||
//ignore
|
||||
|
||||
@@ -5,6 +5,8 @@ declare(strict_types=1);
|
||||
namespace Cheeper\Chapter7\Application\Author\Query;
|
||||
|
||||
//snippet timeline-handler
|
||||
use Cheeper\Chapter7\Application\Cheep\Projection\AddCheepToTimelineProjectionHandler;
|
||||
|
||||
final class TimelineQueryHandler
|
||||
{
|
||||
public function __construct(
|
||||
@@ -15,7 +17,10 @@ final class TimelineQueryHandler
|
||||
public function __invoke(TimelineQuery $query): TimelineQueryResponse
|
||||
{
|
||||
$authorId = $query->authorId();
|
||||
$key = sprintf('author_timeline_projection:%s', $authorId);
|
||||
$key = sprintf(
|
||||
AddCheepToTimelineProjectionHandler::REDIS_KEY_TEMPLATE,
|
||||
$authorId
|
||||
);
|
||||
|
||||
$serializedCheeps = $this->redis->lRange(
|
||||
$key,
|
||||
|
||||
@@ -10,6 +10,8 @@ use Redis;
|
||||
//snippet add-cheep-to-timeline-projector
|
||||
final class AddCheepToTimelineProjectionHandler
|
||||
{
|
||||
public const REDIS_KEY_TEMPLATE = 'author_timeline_projection:%s';
|
||||
|
||||
public function __construct(
|
||||
private Redis $redis,
|
||||
) {
|
||||
@@ -26,7 +28,7 @@ final class AddCheepToTimelineProjectionHandler
|
||||
private function getRedisKey(AddCheepToTimelineProjection $message): string
|
||||
{
|
||||
return sprintf(
|
||||
CreateFollowersCounterProjectionHandler::REDIS_KEY_TEMPLATE,
|
||||
self::REDIS_KEY_TEMPLATE,
|
||||
$message->authorId
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user