EventSauce Documentation

repository·main·Indexed 21 days ago

https://github.com/eventsaucephp/eventsauce

An opinionated library for implementing event sourcing in PHP. EventSauce decouples event storage and queuing from core logic and provides tools for developer productivity, including code generation via the eventsauce/code-generation package and specialized testing utilities via eventsauce/pest-utilities. Key features include support for partial aggregates using the AggregateRootWithAggregates trait, custom type serialization via the SerializablePayload interface, and Anti-Corruption Layers (ACL) for message translation and filtering.

Tokens
34.3K
Snippets
97
Records
140
Agent score
74%

What's inside EventSauce

  1. Get started with EventSauce

    main
    EventSauce is an event sourcing library for PHP designed to focus on developer productivity. It provides a streamlined workflow for implementing event sourcing through the use of code generators and specialized test tooling. To begin using the library, you should follow the installation guide and learn how to define your domain models (Commands, Events, and Aggregate Roots).
  2. What is a Message Outbox and when to use it

    main

    A Message Outbox (or Transactional Outbox) is a pattern used to ensure that event persistence and event dispatching succeed or fail as a single atomic operation.

    In many systems, an aggregate root persists events to a database and then sends them to a queue. Because these are two separate network interactions, one might succeed while the other fails, leading to inconsistency.

    A Message Outbox solves this by buffering events in a separate table within the same database used for event reconstitution. These buffered events are then re-dispatched to a queue at a later time.

    Key Benefits:

    • Atomicity: Ensures that events are only communicated to consumers if they were successfully persisted.
    • At-least-once delivery: Guarantees that events will eventually be dispatched even if the initial dispatch attempt fails.

    Trade-off:

    • Latency: Adds latency to the overall event delivery pipeline because dispatching happens after the database transaction.
  3. What is snapshotting in EventSauce

    main

    Snapshotting is a technique used to optimize the performance of fetching an aggregate root. Instead of loading and applying every single event in an aggregate's stream, you can load a 'snapshot' that represents the aggregate's state at a specific version. This reduces the number of events that need to be processed during reconstitution.

    A snapshot consists of:

    • The aggregate root ID
    • The snapshot state (the internal state of the aggregate)
    • The aggregate root version
  4. What is an AggregateRootRepository?

    main

    An AggregateRootRepository is the central component for managing the lifecycle of aggregate roots in EventSauce. It performs two main roles:

    1. Retrieval (Reconstitution): It fetches the history of events from a MessageRepository and uses them to reconstruct the current state of an aggregate root.
    2. Persistence: It provides the mechanism to persist new events recorded by the aggregate root.

    While you can implement your own, the EventSourcedAggregateRootRepository is the standard implementation provided by the library.

  5. What is message decoration in EventSauce

    main

    Message decoration allows you to add headers to messages to provide extra contextual information before a message is persisted or dispatched.

    By default, the AggregateRootRepository uses the DefaultHeaderDecorator, which automatically handles several important headers:

    • Header::TIME_OF_RECORDING: A precise date/time record of when the message was recorded, essential for replaying events in order and for business analytics.
    • Header::EVENT_TYPE: Ensures the event type is detected and filled.
    • Aggregate Root ID: Pre-processes the ID by converting it to a string and adding type information.
  6. What is event sourcing?

    main

    Event sourcing is a modeling technique that focuses on changes (events) rather than current state. Instead of storing the current state of an entity, you store an immutable, append-only sequence of events that represent historical facts.

    Key components include:

    • Events: Immutable objects representing something that happened in the past (named in past tense). They capture intention and contextual information.
    • Write Models (Decision Models): Models constructed by replaying events to determine the current state and make new decisions.
    • Read Models (Presentational Models): Different ways of viewing the data, often created using projections from the event stream.
  7. Understand the Message object and internal headers

    main

    A Message object acts as an envelope containing an event object and headers. Headers are used for non-domain-event-specific information. EventSauce uses several internal headers, which are accessible via constants on the EventSauce\EventSourcing\Header interface.

    Internal headers include:

    • Header::EVENT_ID (__event_id): The ID of the event (optional but recommended).
    • Header::EVENT_TYPE (__event_type): The type of the event.
    • Header::TIME_OF_RECORDING (__time_of_recording): When the event was recorded.
    • Header::AGGREGATE_ROOT_ID (__aggregate_root_id): The aggregate root ID.
    • Header::AGGREGATE_ROOT_ID_TYPE (__aggregate_root_id_type): The type of aggregate root ID.
    • Header::AGGREGATE_ROOT_VERSION (__aggregate_root_version): The aggregate version (1-based sequence).
  8. What are process managers and how do they work?

    main

    In EventSauce, a process manager is an implementation of the MessageConsumer interface. While projections are used to update read models, process managers are designed to act on events. They allow you to break down large, complex processes into multiple background steps.

    When a process manager reacts to an event, it can trigger new actions by:

    1. Dispatching new commands (e.g., via a command bus).
    2. Using a service layer to trigger external actions.

    This pattern is particularly useful for background tasks that do not require immediate user interaction, ensuring that the main server response is not blocked by long-running workflows.

  9. Understand the Message Outbox pattern

    main
    A Message Outbox (or Transactional Outbox) is used to enable transactional dispatching of messages. This ensures that messages are dispatched within the same database transaction used to persist the messages themselves (or other non-event-sourced models). This pattern is essential for ensuring consistency between state changes and message dispatching to asynchronous consumers.
  10. How to retrieve a specific version of an aggregate

    main

    The AggregateRootRepository does not provide methods to retrieve an aggregate at a specific version. Attempting to do so via the repository is considered an anti-pattern because fetching a specific version is a read operation.

    To compare versions or retrieve historical states, you should use a projection or a read model. Projections can be persistent or in-memory depending on your needs. See the documentation on projections and read models for implementation details.