Skip to content

Commit

Permalink
add traces
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidBadura committed Mar 26, 2024
1 parent e57f368 commit 78b4ccb
Show file tree
Hide file tree
Showing 10 changed files with 432 additions and 62 deletions.
4 changes: 4 additions & 0 deletions config/routes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@ patchlevel_event_sourcing_admin_inspection_show:
patchlevel_event_sourcing_admin_event_index:
path: /event
controller: Patchlevel\EventSourcingAdminBundle\Controller\EventController::indexAction

patchlevel_event_sourcing_admin_graph_index:
path: /graph
controller: Patchlevel\EventSourcingAdminBundle\Controller\GraphController::indexAction
28 changes: 7 additions & 21 deletions public/build/app.css

Large diffs are not rendered by default.

87 changes: 83 additions & 4 deletions src/Controller/EventController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use Patchlevel\EventSourcing\EventBus\ListenerProvider;
use Patchlevel\EventSourcing\Metadata\Event\EventRegistry;
use Patchlevel\EventSourcing\Metadata\Projector\ProjectorMetadataFactory;
use Patchlevel\EventSourcingAdminBundle\Projection\Node;
use Patchlevel\EventSourcingAdminBundle\Projection\TraceProjector;
use Symfony\Component\HttpFoundation\Response;
use Twig\Environment;

Expand All @@ -23,6 +25,7 @@ public function __construct(
private readonly ListenerProvider $listenerProvider,
private readonly iterable $projectors,
private readonly ProjectorMetadataFactory $projectorMetadataFactory,
private readonly TraceProjector|null $traceProjector,
)
{
}
Expand All @@ -35,11 +38,9 @@ public function indexAction(): Response
$events[] = [
'name' => $eventName,
'class' => $eventClass,
'listeners' => array_map(
static fn(ListenerDescriptor $listener) => $listener->name(),
$this->listenerProvider->listenersForEvent($eventClass),
),
'listeners' => $this->listenerMethods($eventClass),
'projectors' => $this->projectorsMethods($eventClass),
'sources' => $this->source($eventClass),
];
}

Expand All @@ -48,6 +49,14 @@ public function indexAction(): Response
]));
}

private function listenerMethods(string $eventClass): array
{
return array_map(
static fn(ListenerDescriptor $listener) => $listener->name(),
$this->listenerProvider->listenersForEvent($eventClass),
);
}

private function projectorsMethods(string $eventClass): array
{
$result = [];
Expand All @@ -70,4 +79,74 @@ private function projectorsMethods(string $eventClass): array

return $result;
}

/**
* @param string $eventClass
* @return list<Node>
*/
private function source(string $eventClass): array
{
$node = $this->findNodeByEventClass($eventClass);

if (!$node) {
return [];
}

return $this->findSources($node);
}

private function findNodeByEventClass(string $eventClass): Node|null
{
if ($this->traceProjector === null) {
return null;
}

$nodes = $this->traceProjector->nodes();

$name = $this->eventRegistry->eventName($eventClass);

foreach ($nodes as $node) {
if ($node->name === $name) {
return $node;
}
}

return null;
}

private function findNodeById(string $id): Node|null
{
if ($this->traceProjector === null) {
return null;
}

$nodes = $this->traceProjector->nodes();

foreach ($nodes as $node) {
if ($node->id === $id) {
return $node;
}
}

return null;
}

/**
* @param Node $node
* @return list<Node>
*/
private function findSources(Node $node): array
{
$links = $this->traceProjector->links();

$result = [];

foreach ($links as $link) {
if ($link->toId === $node->id) {
$result[] = $this->findNodeById($link->fromId);
}
}

return $result;
}
}
52 changes: 26 additions & 26 deletions src/Controller/ProjectionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

namespace Patchlevel\EventSourcingAdminBundle\Controller;

use Patchlevel\EventSourcing\Projection\Projection\ProjectionStatus;
use Patchlevel\EventSourcing\Projection\Projection\RunMode;
use Patchlevel\EventSourcing\Projection\Projectionist\Projectionist;
use Patchlevel\EventSourcing\Projection\Projectionist\ProjectionistCriteria;
use Patchlevel\EventSourcing\Subscription\Status;
use Patchlevel\EventSourcing\Subscription\RunMode;
use Patchlevel\EventSourcing\Subscription\Engine\SubscriptionEngine;
use Patchlevel\EventSourcing\Subscription\Engine\SubscriptionEngineCriteria;
use Patchlevel\EventSourcing\Store\Store;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
Expand All @@ -19,21 +19,21 @@ final class ProjectionController
{
public function __construct(
private readonly Environment $twig,
private readonly Projectionist $projectionist,
private readonly SubscriptionEngine $engine,
private readonly Store $store,
private readonly RouterInterface $router,
) {
}

public function showAction(Request $request): Response
{
$projections = $this->projectionist->projections();
$subscriptions = $this->engine->subscriptions();
$messageCount = $this->store->count();

$groups = [];

foreach ($projections as $projection) {
$groups[$projection->group()] = true;
foreach ($subscriptions as $subscription) {
$groups[$subscription->group()] = true;
}

$filteredProjections = [];
Expand All @@ -43,31 +43,31 @@ public function showAction(Request $request): Response
$status = $request->get('status');


foreach ($projections as $projection) {
if ($search && !str_contains($projection->id(), $search)) {
foreach ($subscriptions as $subscription) {
if ($search && !str_contains($subscription->id(), $search)) {
continue;
}

if ($group && $projection->group() !== $group) {
if ($group && $subscription->group() !== $group) {
continue;
}

if ($mode && $projection->runMode()->value !== $mode) {
if ($mode && $subscription->runMode()->value !== $mode) {
continue;
}

if ($status && $projection->status()->value !== $status) {
if ($status && $subscription->status()->value !== $status) {
continue;
}

$filteredProjections[] = $projection;
$filteredProjections[] = $subscription;
}

return new Response(
$this->twig->render('@PatchlevelEventSourcingAdmin/projection/show.html.twig', [
'projections' => $filteredProjections,
'messageCount' => $messageCount,
'statuses' => array_map(fn (ProjectionStatus $status) => $status->value, ProjectionStatus::cases()),
'statuses' => array_map(fn (Status $status) => $status->value, Status::cases()),
'modes' => array_map(fn (RunMode $mode) => $mode->value, RunMode::cases()),
'groups' => array_keys($groups),
]),
Expand All @@ -76,10 +76,10 @@ public function showAction(Request $request): Response

public function rebuildAction(string $id): Response
{
$criteria = new ProjectionistCriteria([$id]);
$criteria = new SubscriptionEngineCriteria([$id]);

$this->projectionist->remove($criteria);
$this->projectionist->boot($criteria);
$this->engine->remove($criteria);
$this->engine->boot($criteria);

return new RedirectResponse(
$this->router->generate('patchlevel_event_sourcing_admin_projection_show'),
Expand All @@ -88,9 +88,9 @@ public function rebuildAction(string $id): Response

public function pauseAction(string $id): Response
{
$criteria = new ProjectionistCriteria([$id]);
$criteria = new SubscriptionEngineCriteria([$id]);

$this->projectionist->pause($criteria);
$this->engine->pause($criteria);

return new RedirectResponse(
$this->router->generate('patchlevel_event_sourcing_admin_projection_show'),
Expand All @@ -99,9 +99,9 @@ public function pauseAction(string $id): Response

public function bootAction(string $id): Response
{
$criteria = new ProjectionistCriteria([$id]);
$criteria = new SubscriptionEngineCriteria([$id]);

$this->projectionist->boot($criteria);
$this->engine->boot($criteria);

return new RedirectResponse(
$this->router->generate('patchlevel_event_sourcing_admin_projection_show'),
Expand All @@ -110,9 +110,9 @@ public function bootAction(string $id): Response

public function reactivateAction(string $id): Response
{
$criteria = new ProjectionistCriteria([$id]);
$criteria = new SubscriptionEngineCriteria([$id]);

$this->projectionist->reactivate($criteria);
$this->engine->reactivate($criteria);

return new RedirectResponse(
$this->router->generate('patchlevel_event_sourcing_admin_projection_show'),
Expand All @@ -121,9 +121,9 @@ public function reactivateAction(string $id): Response

public function removeAction(string $id): Response
{
$criteria = new ProjectionistCriteria([$id]);
$criteria = new SubscriptionEngineCriteria([$id]);

$this->projectionist->remove($criteria);
$this->engine->remove($criteria);

return new RedirectResponse(
$this->router->generate('patchlevel_event_sourcing_admin_projection_show'),
Expand Down
2 changes: 1 addition & 1 deletion src/Decorator/RequestIdDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Patchlevel\EventSourcingAdminBundle\Decorator;

use Patchlevel\EventSourcing\Repository\MessageDecorator\MessageDecorator;
use Patchlevel\EventSourcing\EventBus\Message;
use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcingAdminBundle\Listener\RequestIdListener;
use Symfony\Component\HttpFoundation\RequestStack;

Expand Down
20 changes: 15 additions & 5 deletions src/DependencyInjection/PatchlevelEventSourcingAdminExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,29 @@
use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootMetadataFactory;
use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootRegistry;
use Patchlevel\EventSourcing\Metadata\Event\EventRegistry;
use Patchlevel\EventSourcing\Metadata\Projector\ProjectorMetadataFactory;
use Patchlevel\EventSourcing\Projection\Projectionist\Projectionist;
use Patchlevel\EventSourcing\Metadata\Subscriber\SubscriberMetadataFactory;
use Patchlevel\EventSourcing\Serializer\EventSerializer;
use Patchlevel\EventSourcing\Snapshot\SnapshotStore;
use Patchlevel\EventSourcing\Store\Store;
use Patchlevel\EventSourcing\Subscription\Engine\SubscriptionEngine;
use Patchlevel\EventSourcingAdminBundle\Controller\DefaultController;
use Patchlevel\EventSourcingAdminBundle\Controller\EventController;
use Patchlevel\EventSourcingAdminBundle\Controller\GraphController;
use Patchlevel\EventSourcingAdminBundle\Controller\InspectionController;
use Patchlevel\EventSourcingAdminBundle\Controller\ProjectionController;
use Patchlevel\EventSourcingAdminBundle\Controller\StoreController;
use Patchlevel\EventSourcingAdminBundle\Decorator\RequestIdDecorator;
use Patchlevel\EventSourcingAdminBundle\Listener\RequestIdListener;
use Patchlevel\EventSourcingAdminBundle\Listener\TokenMapperListener;
use Patchlevel\EventSourcingAdminBundle\Projection\TraceProjector;
use Patchlevel\EventSourcingAdminBundle\TokenMapper;
use Patchlevel\EventSourcingAdminBundle\Twig\EventSourcingAdminExtension;
use Patchlevel\EventSourcingAdminBundle\Twig\HeroiconsExtension;
use Patchlevel\EventSourcingAdminBundle\Twig\InspectionExtension;
use Patchlevel\Hydrator\Hydrator;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
Expand Down Expand Up @@ -83,7 +85,7 @@ public function load(array $configs, ContainerBuilder $container): void
$container->register(ProjectionController::class)
->setArguments([
new Reference('twig'),
new Reference(Projectionist::class),
new Reference(SubscriptionEngine::class),
new Reference(Store::class),
new Reference(RouterInterface::class),
])
Expand All @@ -95,7 +97,8 @@ public function load(array $configs, ContainerBuilder $container): void
new Reference(EventRegistry::class),
new Reference(ListenerProvider::class),
new TaggedIteratorArgument('event_sourcing.projector'),
new Reference(ProjectorMetadataFactory::class),
new Reference(SubscriberMetadataFactory::class),
new Reference(TraceProjector::class, ContainerInterface::NULL_ON_INVALID_REFERENCE),
])
->addTag('controller.service_arguments');

Expand Down Expand Up @@ -146,5 +149,12 @@ public function load(array $configs, ContainerBuilder $container): void
'method' => '__invoke',
'priority' => -200,
]);

$container->register(TraceProjector::class)
->setArguments([
new Reference('doctrine.dbal.projection_connection'),
new Reference(EventRegistry::class),
])
->addTag('event_sourcing.projector');
}
}
30 changes: 30 additions & 0 deletions src/Projection/Link.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Patchlevel\EventSourcingAdminBundle\Projection;

use JsonSerializable;

final class Link implements JsonSerializable
{
public readonly string $id;

public function __construct(
public readonly string $fromId,
public readonly string $toId,
) {
$this->id = sha1($fromId . '->' . $toId);
}

public function __toString(): string
{
return $this->fromId . ' -> ' . $this->toId;
}

public function jsonSerialize(): array
{
return [
'fromId' => $this->fromId,
'toId' => $this->toId,
];
}
}
Loading

0 comments on commit 78b4ccb

Please sign in to comment.