Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
💡 Description
This pull request introduces event lifecycle hooks -- the ability to register callbacks to be run before and after event dispatch, as well as on listener failure -- enabling developers to implement cross-cutting concerns like logging, metrics, validation, and error handling in a clean, reusable way across event-driven applications.
Primary Functionality
before
hook allows callbacks to be registered against one or more (or all) events, to be run before the event is dispatched to listeners.after
hook allows callbacks to be registered against one or more (or all) events, to be run after all listeners have completed successfully.failure
hook allows callbacks to be registered against one or more (or all) events, to be run on listener failure.Additional Functionality
EventPropagationException
can be thrown in abefore
callback to prevent dispatch to subsequent callbacks or listeners.before
callbacks are invoked in FIFO order, those registered as wildcards (all events), followed by those registered against the specific event, and finally those implemented on the event itself, whileafter
andfailure
are invoked in LIFO order those implemented on the event itself, followed by those registered against the specific event, and finally those registered as wildcards (all events).🏗️ Usage
🪵 Changelog
getContainer()
.EventHooks
trait, enhancedinvokeListeners()
to trigger event lifecycle callbacks when present, replaced container calls withgetContainer()
.before()
,after()
, andfailure()
as well ascallbacks()
.EventHooks
andDispatcher
integration, covering registration, invocation, and error handling.♻ Backward Compatibility
The feature is 100% opt-in and fully backward compatible, introducing no breaking changes:
Dispatcher::invokeListeners()
), the code is entirely additive; the behavior ofDispatcher::invokeListeners()
is unchanged if the feature is not utilized.💥 Performance
hasCallbacks()
is utilized at the integration point inDispatcher::invokeListeners()
to skip the more expensive callback aggregation when none exist for the hook/event.aggregateCalllbacks()
.hasCallbacks()
.✅ Testing
A robust set of tests is included with the pull request:
✓ Callback Registration
✓ Callback Aggregation
✓ Callback Invocation
✓ Event Propagation
✓ Hook & Callback Validation
✓ Callback Detection and Memoization
⚙️ Behavior
🔮 Future Possibilities
EventPropagationException
is thrown.💁🏼♂️ The author is available for hire -- inquire at [email protected].