Download the PHP package projectsaturnstudios/pss-event-sourcing without Composer
On this page you can find all versions of the php package projectsaturnstudios/pss-event-sourcing. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download projectsaturnstudios/pss-event-sourcing
More information about projectsaturnstudios/pss-event-sourcing
Files in projectsaturnstudios/pss-event-sourcing
Package pss-event-sourcing
Short Description Spatie Event Sourcing using Spatie Laravel-Data Objects!
License proprietary
Informations about the package pss-event-sourcing
Project Saturn Studios - Laravel ES Utilities 🚀
Supercharge your Spatie Event Sourcing with the elegance of Spatie's Laravel-Data objects and the power of Loris Leiva's Laravel Actions. This package is all about making event sourcing in Laravel a smoother, more typed, and downright enjoyable ride.
📜 Table of Contents
- 🤔 Why This Package?
- ✨ Features List
- Installation
- Configuration
- How to Rock It (Usage Guide)
- Testing Your Masterpiece
- Advanced Scenarios / Cookbook
- Contributing
- Support & Contact
- License
- Credits & Thanks
- README Change Log
🤔 Why This Package?
Event sourcing is a powerful pattern, and Spatie's laravel-event-sourcing
package provides a rock-solid foundation for it in Laravel. So, why add another layer with laravel-es-utilities
? Glad you asked, partner. This package is all about taking that solid foundation and making your developer experience (DX) even smoother, more robust, and, dare we say, more enjoyable.
Here's the lowdown on what this package brings to your shindig:
-
🤠 Enhanced Type Safety & Clarity with
DataEvent
s:- Problem: Traditional event payloads can sometimes be loose arrays or objects, leading to uncertainty about their structure.
- Solution: We integrate
spatie/laravel-data
directly into your event sourcing workflow. By defining your events as strongly-typedDataEvent
objects (which are essentiallySpatie\LaravelData\Data
objects tailored for event sourcing), you get auto-completion, compile-time(ish) checks via static analysis, and runtime validation. This means fewer bugs and clearer contracts for what your events represent.
-
🎬 Structured & Testable Commands with
EventCommand
s:- Problem: Command handling logic can sometimes become scattered or less defined.
- Solution: Leveraging
lorisleiva/laravel-actions
, we promote a pattern ofEventCommand
classes. These are dedicated action classes that encapsulate the logic for validating a command, executing business rules, and ultimately producing aDataEvent
. This makes your command logic more organized, easier to test in isolation, and reusable.
-
⚙️ Streamlined Workflow:
- Problem: Wiring up custom serializers or ensuring robust event persistence can require boilerplate.
- Solution: This package comes with:
- A pre-configured
EventSerializer
that understands how to handleDataEvent
objects out-of-the-box. - A
RetryPersistMiddleware
(applied by default via theevent_command()
helper) that automatically retries event persistence on common database issues, adding resilience to your system. - The convenient
event_command()
helper function to dispatch yourEventCommand
s with sensible defaults.
- A pre-configured
- 🚀 Improved Developer Experience (DX):
- Overall Benefit: By combining these elements, the goal is to reduce boilerplate, increase clarity, improve testability, and make the overall process of building event-sourced applications in Laravel more intuitive and less error-prone. You get to focus more on your business logic and less on the plumbing.
In short, if you love spatie/laravel-event-sourcing
but wished for tighter integration with typed data objects and a more structured approach to commands, laravel-es-utilities
is here to be your new best friend.
✨ Features List
This package is packed with goodies to make your event sourcing journey in Laravel smoother. Here are the highlights:
-
Typed
DataEvent
Objects:- Leverages
spatie/laravel-data
to allow you to define your events as strongly-typed Data objects. - Events should extend
ProjectSaturnStudios\EventSourcing\Events\DataEvent
. - Benefits: Clear event contracts, auto-completion, validation, and easier refactoring.
- Leverages
-
Structured
EventCommand
Actions:- Promotes the use of
lorisleiva/laravel-actions
for handling commands. - Commands can extend the base
ProjectSaturnStudios\EventSourcing\EventCommands\EventCommand
. - Benefits: Encapsulated command logic, improved testability, and reusability of commands.
- Promotes the use of
-
Convenient
event_command()
Helper:- A global helper function
event_command(YourEventCommand $command, array $middleware = [...])
to easily dispatch yourEventCommand
instances. - Automatically applies
RetryPersistMiddleware
by default.
- A global helper function
-
Resilient
RetryPersistMiddleware
:- Spatie Command Bus middleware that automatically retries event persistence if common database issues (like
PDOException
orCouldNotPersistAggregate
) occur. - Enhances the reliability of your event stream.
- Spatie Command Bus middleware that automatically retries event persistence if common database issues (like
-
Tailored
EventSerializer
:- A custom event serializer (
ProjectSaturnStudios\EventSourcing\Serializers\EventSerializer
) that understands how to serialize and deserialize yourDataEvent
objects usingspatie/laravel-data
's capabilities. - Automatically configured by the package's service provider.
- A custom event serializer (
-
PSSEventSourcingServiceProvider
:- The package's service provider automatically merges necessary configurations, primarily setting up the custom
EventSerializer
.
- The package's service provider automatically merges necessary configurations, primarily setting up the custom
-
Flexible
AlternativeAggregateRoot
:- An optional base class (
ProjectSaturnStudios\EventSourcing\Aggregates\AlternativeAggregateRoot
) for your aggregates if you need to specify custom event or snapshot repositories.
- An optional base class (
-
Helpful
app_queue()
Helper:- A utility function
app_queue('your-queue-name')
to easily prefix queue names based on theQS_PREFIX
environment variable, useful for namespacing.
- A utility function
- Centralized
DispatchEventCommand
Action:- An underlying action (
ProjectSaturnStudios\EventSourcing\Actions\DispatchEventCommand
) used by theevent_command()
helper to integrate with Spatie's Command Bus and apply middleware.
- An underlying action (
📦 Installation
You can install the package via Composer:
The package leverages Laravel's package auto-discovery, so you typically won't need to manually register the service provider (ProjectSaturnStudios\EventSourcing\Providers\PSSEventSourcingServiceProvider
).
This service provider will automatically merge the necessary configuration to use the custom ProjectSaturnStudios\EventSourcing\Serializers\EventSerializer
for handling DataEvent
objects. This ensures your typed event data is correctly serialized and deserialized using spatie/laravel-data
capabilities.
Optional: Publishing Configuration
If you wish to customize the event sourcing configuration further (beyond what this package provides by default), you can publish Spatie's main event sourcing configuration file. Note that this package already sets the recommended event_serializer
. If you publish and modify Spatie's config, ensure you retain or re-configure the event_serializer
to point to ProjectSaturnStudios\EventSourcing\Serializers\EventSerializer::class
if you want to continue using this package's DataEvent serialization.
To publish Spatie's configuration (if you haven't already for spatie/laravel-event-sourcing
):
This will create a config/event-sourcing.php
file in your application's config directory.
Again, for this package (projectsaturnstudios/laravel-es-utilities
) to work as intended with DataEvent
objects, the event_serializer
in that published config should be:
Our package attempts to set this for you by default through its own service provider's config merging. Publishing is only needed if you require deeper customization of other Spatie event sourcing settings.
⚙️ Configuration
This package is designed to work with minimal configuration out-of-the-box.
Event Serializer
The most crucial piece of configuration is the event_serializer
. Our ProjectSaturnStudios\EventSourcing\Providers\PSSEventSourcingServiceProvider
automatically merges its configuration to set the event_serializer
in your config/event-sourcing.php
to use ProjectSaturnStudios\EventSourcing\Serializers\EventSerializer::class
.
This ensures that your DataEvent
objects are correctly handled. No manual configuration is typically needed for this.
If you publish the spatie/laravel-event-sourcing
configuration file (php artisan vendor:publish --provider="Spatie\EventSourcing\EventSourcingServiceProvider" --tag="event-sourcing-config"
), you'll see this setting:
If you override this, ensure you understand the implications for DataEvent
serialization.
Queue Prefixing (app_queue()
helper)
The app_queue(string $key): string
helper function allows you to prefix your queue names. It looks for an environment variable:
QS_PREFIX
: If set, this prefix (e.g.,my-app-
) will be prepended to the queue key you provide. Example:app_queue('events')
withQS_PREFIX=prod
would result inprod-events
.
This is useful for namespacing queues in different environments or applications sharing a Redis instance.
RetryPersistMiddleware
The ProjectSaturnStudios\EventSourcing\Middleware\RetryPersistMiddleware
used by the event_command()
helper defaults to 3 retry attempts. If you were to use this middleware manually with Spatie's Command Bus, you could configure the number of retries via its constructor:
However, when using the event_command()
helper, it defaults to 3 retries, which is generally a sensible default.
Other Spatie Event Sourcing Configuration
For all other event sourcing configurations (e.g., projectors, reactors, stored event repository, snapshot repository), please refer to the official spatie/laravel-event-sourcing
package documentation and its config/event-sourcing.php
file. This package primarily focuses on enhancing the event and command handling aspects.
🚀 How to Rock It (Usage Guide)
Alright, let's get down to brass tacks. Here's how you can use this package to make your event sourcing life a little more zen.
Defining Your DataEvent
First up, you'll want to define your domain events as DataEvent
objects. These are essentially Spatie\LaravelData\Data
objects that also extend ProjectSaturnStudios\EventSourcing\Events\DataEvent
. This base class provides the necessary integration with Spatie's event sourcing system and Laravel Data's features.
Example: Let's say we're building a simple "Todo" application and want an event for when a task is created.
Key Benefits Here:
- Strong Typing:
taskUuid
,description
,status
, andcreatedAt
are all typed. - Readonly Properties: Good practice for immutable event data.
- Laravel Data Features: You can use all of
spatie/laravel-data
's features like casting, validation attributes (though validation is often done in commands), custom creators, etc., if needed. - Serialization: The configured
EventSerializer
will automatically uselaravel-data
'stoJson()
andfrom()
methods.
Crafting Your EventCommand
Next, you'll create EventCommand
classes. These are responsible for taking input, performing any necessary validation or business logic, and then creating the appropriate DataEvent
. We recommend using lorisleiva/laravel-actions
for these commands, and they can extend the base ProjectSaturnStudios\EventSourcing\EventCommands\EventCommand
(though this base class is simple and mainly for type-hinting or namespacing).
Example: A command to create our TodoTask
.
Key Points for EventCommand
s:
- Single Responsibility: Each command handles one specific action.
- Data In, Event (indirectly) Out: Takes input data, produces a
DataEvent
which is then recorded on an aggregate. - Validation: Use
laravel-actions
' validation features to ensure data integrity before processing. - Interaction with Aggregates: The command handler is where you'll typically retrieve an aggregate, call its methods (which in turn record events), and persist the aggregate.
Dispatching with event_command()
Once you have your EventCommand
defined, you'll want to dispatch it. This package provides a convenient global helper function event_command()
for this purpose.
This helper function uses the ProjectSaturnStudios\EventSourcing\Actions\DispatchEventCommand
action internally, which in turn uses Spatie's Command Bus. By default, if you don't specify any middleware, event_command()
applies the ProjectSaturnStudios\EventSourcing\Middleware\RetryPersistMiddleware
.
Example: Dispatching our CreateTodoTask
command.
If you need to use custom middleware, or want to change the retry behavior:
Working with Aggregates
Your EventCommand
handlers will typically interact with Aggregate Roots (from spatie/laravel-event-sourcing
). The aggregate is responsible for upholding business rules and recording events that result from command processing.
Example Aggregate (TodoTaskAggregate
):
Let's sketch out what our TodoTaskAggregate
might look like. It would extend Spatie\EventSourcing\AggregateRoots\AggregateRoot
(or our ProjectSaturnStudios\EventSourcing\Aggregates\AlternativeAggregateRoot
if you need its specific features).
Key Interactions:
- Recording Events: Inside your aggregate methods (like
createTask
orchangeDescription
), you call$this->recordThat(new YourDataEvent(...))
to stage an event. - Applying Events: For each event type, you create a corresponding
apply<EventName>
method (e.g.,applyTodoTaskCreated
). This method is responsible for changing the state of the aggregate based on the event data. This is how the aggregate rebuilds its state when loaded from history. - Persisting: After calling methods on your aggregate in your
EventCommand
, you must call$aggregate->persist()
to save all recorded events to the database.
Revised CreateTodoTask
Command (showing aggregate interaction more clearly):
Implicit Benefits: RetryPersistMiddleware
& EventSerializer
It's worth reiterating two key components that work quietly in the background to make your life easier when using the patterns described above:
-
EventSerializer
:- As configured by this package, the
ProjectSaturnStudios\EventSourcing\Serializers\EventSerializer
automatically handles the serialization of yourDataEvent
objects to JSON for storage and deserialization back into their strongly-typedSpatie\LaravelData\Data
forms when events are retrieved. - You generally don't need to think about this; it just works, ensuring your typed event data is preserved correctly.
- As configured by this package, the
RetryPersistMiddleware
:- When you dispatch commands using the
event_command()
helper, theProjectSaturnStudios\EventSourcing\Middleware\RetryPersistMiddleware
is active by default. - If your command handler attempts to persist an aggregate (
$aggregate->persist()
) and a transient database error occurs (like aPDOException
or Spatie'sCouldNotPersistAggregate
), this middleware will automatically retry the entire command execution a few times. - This adds a significant layer of resilience against temporary network glitches or database deadlocks without you needing to write custom retry logic in every command.
- When you dispatch commands using the
These features are designed to provide a more robust and developer-friendly experience with minimal effort on your part.
✅ Testing Your Masterpiece
Testing is crucial for event-sourced applications. Here's how you can approach testing different parts of your system when using laravel-es-utilities
.
Testing EventCommand
Actions
Since your EventCommand
classes are built using lorisleiva/laravel-actions
, you can test them like any other Laravel Action. You can unit test them by directly instantiating and calling the handle
method, or test them as part of a feature test.
Key things to assert:
- Validation Rules: Ensure your command's
rules()
method correctly validates input. - Event Emission (via Aggregates): The primary goal is often to ensure the correct
DataEvent
(s) are recorded on an aggregate. - State Changes on Aggregates: Verify that the aggregate's state changes as expected after applying the events triggered by the command.
Spatie's laravel-event-sourcing
package provides excellent testing tools for aggregates:
Testing Aggregates
Spatie's laravel-event-sourcing
package provides powerful testing methods directly on your aggregate roots.
Key aggregate testing methods:
$aggregateRoot->assertRecorded($expectedEvents)
$aggregateRoot->assertNotRecorded($unexpectedEvents)
$aggregateRoot->assertEventRecorded($eventClass, Closure $callback = null)
$aggregateRoot->assertNothingRecorded()
$aggregateRoot->flushRecordedEvents()
Testing Projectors and Reactors
Refer to the spatie/laravel-event-sourcing
documentation for detailed guidance on testing projectors and reactors. They also have dedicated testing tools.
This package focuses on the command and event creation side, so ensure your DataEvent
objects and EventCommand
actions integrate well with your aggregates, and then leverage Spatie's tools for the rest.
🔮 Advanced Scenarios / Cookbook
Here are a couple of scenarios or tools within the package that go beyond the basic setup.
Using AlternativeAggregateRoot
If you have specific needs for how your aggregate roots interact with event or snapshot repositories (for example, using different database connections or custom repository implementations for certain aggregates), this package provides an AlternativeAggregateRoot
.
You can extend ProjectSaturnStudios\EventSourcing\Aggregates\AlternativeAggregateRoot
instead of the default Spatie\EventSourcing\AggregateRoots\AggregateRoot
. Then, within your aggregate, you can specify the classes for your custom repositories:
Your custom repository classes (MyCustomEventRepository
, MyCustomSnapshotRepository
) must implement the respective interfaces expected by Spatie's event sourcing package (e.g., Spatie\EventSourcing\StoredEvents\Repositories\StoredEventRepository
and Spatie\EventSourcing\Snapshots\SnapshotRepository
).
This gives you fine-grained control over persistence mechanisms for specific aggregates without altering the global defaults.
Using the app_queue()
Helper
The app_queue(string $key): string
helper function is a simple utility for prefixing your queue names based on an environment variable. This is particularly useful if you're running multiple applications or environments that might share a queueing backend (like Redis) and you want to avoid queue name collisions.
How it works:
-
Define an environment variable, for example, in your
.env
file: -
When you use the helper:
- If
QS_PREFIX
is not set or is empty,app_queue('events')
will simply return'events'
.
You can use this helper anywhere you define queue names, such as in your event listeners, jobs, or in the Spatie event sourcing configuration (config/event-sourcing.php
for the main event queue).
Example in config/event-sourcing.php
:
This helps keep your queue management clean and organized across different environments.
🙌 Contributing
We welcome contributions from the community! If you're interested in contributing to this package, please follow these steps:
- Fork the repository on GitHub.
- Create a new branch for your feature or bug fix.
- Make your changes in the new branch.
- Write tests for your changes.
- Submit a pull request.
🙌 Support & Contact
If you encounter any issues or have questions about this package, please feel free to open an issue on GitHub or contact us directly.
📄 License
This package is open-source and released under the MIT License. See the LICENSE file for more information.
📋 Credits & Thanks
This package was created by Project Saturn Studios. We're grateful for the contributions of the community and the support of our users.
📜 README Change Log
See the CHANGELOG file for a detailed history of changes to this README.
All versions of pss-event-sourcing with dependencies
ext-pdo Version *
spatie/laravel-data Version ^4.11
lorisleiva/laravel-actions Version ^2.6
spatie/laravel-event-sourcing Version ^7.3
ramsey/uuid Version ^4.7