Today we are talking about two releases for our PHP
library patchlevel/event-sourcing:
version 3.9.0 and
version 3.10.0!
The first release, 3.9.0
, was a smaller one mostly focused on some DX improvements. The second, 3.10.0
, comes with
some neat features for the subscription engine along with various updates and deprecations. So, let's start going
through these changes.
3.9.0
EventDispatcher in Worker
We made a change
in patchlevel/worker which makes using the worker even more valuable. You can
now utilize the events from the worker by adding your own listeners to its internal events. Previously, we already used
an event dispatcher internally, but you could not add any listeners to it.
Now this is possible, which can come in handy if, for example, you are using a long-running process, like the
subscription engine, and have an error tracking tool such as Sentry in place. Without these changes, it was not possible
to manually flush messages to send them to Sentry if something happened during the execution of the subscription engine.
In the bundle, we added a ResetServicesListener
which already
takes advantage of this new possibility. Now, after every run of the subscription engine, we are executing Symfony's
ServiceResetter
. This makes the subscription engine even more resource-efficient than before. Also, regarding the
Sentry example, if you are using the Monolog variant, this now automatically flushes all errors to Sentry.
ChildAggregates: Usage of Private Properties
We streamlined the usage of ChildAggregate
s based on
a user request. The issue was that the ChildAggregate
was a
private property of the aggregate and was implemented using our BasicAggregateRoot
abstract class. This combination
led to an error due to visibility issues, which we have resolved by using reflection.
Keep in mind that the ChildAggregate
feature is still experimental and that we also have another feature which we
believe is better suited in almost every
case: micro aggregates. You should probably
use that feature instead of ChildAggregates
.
3.10.0
PHP 8.4 Support
We officially added PHP 8.4 support, and not much work was needed. PHP 8.4 is now included in our test matrix;
therefore, everything is tested with this new version.
Deprecation of AggregateId ArgumentResolver
We deprecated the AggregateIdArgumentResolver
because we believe that if you need it, you have already done something
wrong. The Aggregate ID should be part of your event itself and not only part of our metadata. That's why we want to
remove this class from our library, as it may lead to poor event design.
Subscription Engine: Different RetryStrategies for Subscribers
We already supported defining a RetryStrategy
for the subscription engine to handle failed attempts. Now, we are
taking it a step further by enabling you to define different
strategies for your subscribers. This gives you more control over the behavior when something goes wrong.
To make this work, we now have a RetryStrategyRepository
which holds a map of unique name to strategy. This name
is then used for configuration.
To configure a retry strategy for a
subscriber, we offer a new attribute #[RetryStrategy]
that expects the name of the strategy. The library comes with
two strategies configured out of the box: default and no_retry. The default strategy utilizes the
ClockBasedRetryStrategy
, configured with 5 attempts, a base delay of 5 seconds, and a factor of 2. The
no_retry strategy is self-explanatory — it simply does not retry.
Subscription Engine: OnFailed Hook
In version 3.7.0
, we added a new status for subscriptions: the failed status. This status is reached when an error
occurs and the retry strategy fails to recover from it. Now, we have polished this further by allowing you to easily
hook into this case. We added a #[OnFailed]
attribute that you can add to a method on the subscriber
to handle the failed message. For example, you
can add this message to a DeadLetter queue for later processing.
By doing this, you free the subscription engine from holding the subscription in the failed state. After successfully
handling the #[OnFailed]
method, the subscription status will move from failed
to active
. When using this with
projections, be aware that data may then be missing from the table.
Conclusion
These two releases deliver some neat features, especially around the subscription engine, making it even more efficient
and powerful. As always, we would love to hear your feedback about these features or any other topics related to event
sourcing, so don't hesitate to open an issue on GitHub or start
a discussion there. The next release is already in the
pipeline, so stay tuned.