Implementando Event Sourcing Simplificado con PHP y Doctrine
Event Sourcing es un patrón de diseño donde el estado de una aplicación se deriva de una secuencia de eventos. En lugar de persistir el estado actual, se guardan todos los eventos que causaron cambios en ese estado. Esto ofrece ventajas como auditoría completa, capacidad de reconstruir el estado en cualquier momento, y una mejor base para funcionalidades como CQRS (Command Query Responsibility Segregation). Este post presenta una implementación simplificada de Event Sourcing en PHP, utilizando Doctrine para la persistencia.
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="events")
*/
class Event
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue
*/
private $id;
/**
* @ORM\Column(type="string")
*/
private $eventType;
/**
* @ORM\Column(type="json")
*/
private $payload;
/**
* @ORM\Column(type="datetime_immutable")
*/
private $occurredAt;
public function __construct(string $eventType, array $payload)
{
$this->eventType = $eventType;
$this->payload = $payload;
$this->occurredAt = new \DateTimeImmutable();
}
public function getEventType(): string
{
return $this->eventType;
}
public function getPayload(): array
{
return $this->payload;
}
public function getOccurredAt(): \DateTimeImmutable
{
return $this->occurredAt;
}
}
El código anterior define la entidad Event
que se persistirá en la base de datos. Cada evento tiene un eventType
(un string que describe el tipo de evento, por ejemplo, 'UserCreated' o 'OrderPlaced'), un payload
(un array asociativo que contiene los datos relevantes del evento), y una marca de tiempo occurredAt
. Doctrine se encarga de mapear esta clase a una tabla llamada "events".
<?php
use Doctrine\ORM\EntityManagerInterface;
class EventStore
{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function append(Event $event): void
{
$this->entityManager->persist($event);
$this->entityManager->flush();
}
public function replayEvents(): array
{
return $this->entityManager
->getRepository(Event::class)
->findBy([], ['occurredAt' => 'ASC']);
}
}
La clase EventStore
gestiona la persistencia y recuperación de los eventos. El método append
persiste un nuevo evento en la base de datos, y el método replayEvents
recupera todos los eventos en el orden en que ocurrieron. Para reconstruir el estado, se iteraría sobre los eventos recuperados y se aplicarían a un objeto "agregado" (la entidad que representa el estado). Este enfoque simplificado se centra en la persistencia, dejando la lógica de aplicación de los eventos al dominio.
Para usar este sistema, inyectarías el EntityManagerInterface
en el EventStore
(por ejemplo, usando un contenedor de dependencias). Luego, podrías crear instancias de Event
y persistirlas usando $eventStore->append($event)
. Para reconstruir el estado, usarías $eventStore->replayEvents()
y aplicarías cada evento a tu agregado.
No hay comentarios:
Publicar un comentario