VOOZH about

URL: https://deepwiki.com/hypervel/event/4.2-handling-events-after-commit

⇱ Handling Events After Commit | hypervel/event | DeepWiki


Loading...
Menu

Handling Events After Commit

This document covers how to configure individual event listeners to execute after database transaction commits, using the ShouldHandleEventsAfterCommit interface and afterCommit property. This provides granular control over which listeners are transaction-aware while allowing events to dispatch immediately.

For information about deferring the entire event dispatch until after commit, see Dispatching Events After Commit.

Purpose and Scope

The ShouldHandleEventsAfterCommit interface and afterCommit property allow you to defer specific listener execution until database transactions are successfully committed. This differs from ShouldDispatchAfterCommit by operating at the listener level rather than the event level - the event is dispatched immediately, but individual listeners marked for post-commit execution are deferred.

This feature is essential when listeners perform operations that should only occur if the current database transaction succeeds, such as sending notifications, clearing caches, or triggering external API calls.

Implementation Approaches

There are two ways to mark a listener for post-commit execution:

Interface-Based Approach

Implement the ShouldHandleEventsAfterCommit interface on your listener class:


Property-Based Approach

Add an afterCommit property to your listener class:


Sources: src/Contracts/ShouldHandleEventsAfterCommit.php7-9 src/EventDispatcher.php287-292

Transaction Detection and Callback Registration

The EventDispatcher automatically detects listeners that should execute after commit and registers them with the TransactionManager:

Transaction Detection Flow


The detection occurs in createClassCallable() at src/EventDispatcher.php279-282 after determining the listener is not queued. The handlerShouldBeDispatchedAfterDatabaseTransactions() method at src/EventDispatcher.php287-292 performs the actual check.

Sources: src/EventDispatcher.php263-282 src/EventDispatcher.php287-292 src/EventDispatcher.php428-440

Internal Execution Flow

When a listener is marked for post-commit execution, EventDispatcher creates a closure that defers the actual listener execution:

Callback Registration and Execution Sequence


The createCallbackForListenerRunningAfterCommits() method at src/EventDispatcher.php428-440 creates a closure that:

  1. Captures the listener instance, method name, and event payload
  2. Registers with TransactionManager via addCallback() at line 434
  3. Executes $listener->{$method}(...$payload) when the transaction commits
ComponentResponsibility
createCallbackForListenerRunningAfterCommits()Creates deferred execution closure (lines 428-440)
resolveTransactionManager()->addCallback()Stores callback for post-commit execution (line 434)
Generated ClosureCaptures listener context and executes after commit (lines 435-437)

Sources: src/EventDispatcher.php428-440

Listener Detection Logic

The handlerShouldBeDispatchedAfterDatabaseTransactions() method at src/EventDispatcher.php287-292 determines if a listener should be deferred:

Detection Decision Tree


The method at src/EventDispatcher.php287-292 implements this logic:


This ensures that:

  1. Either the afterCommit property is truthy OR the listener implements ShouldHandleEventsAfterCommit
  2. AND a TransactionManager is available via resolveTransactionManager()
  3. If no transaction manager exists, listeners execute immediately regardless of configuration

Sources: src/EventDispatcher.php287-292 src/EventDispatcher.php377-382

Integration with Class-Based Listeners

The post-commit handling integrates with the EventDispatcher class-based listener resolution in createClassCallable():

Listener Resolution Precedence


The precedence order in createClassCallable() at src/EventDispatcher.php263-282:

  1. Queued listeners (ShouldQueue) - Checked first at line 273, overrides all other behavior
  2. Post-commit listeners (ShouldHandleEventsAfterCommit or afterCommit) - Checked at line 279
  3. Regular listeners - Default behavior, returned at line 281

Sources: src/EventDispatcher.php263-282 src/EventDispatcher.php395-408

Combining with Queued Listeners

When a listener implements both ShouldQueue and ShouldHandleEventsAfterCommit, or has an afterCommit property, the queue behavior takes precedence. The afterCommit configuration is then propagated to the CallQueuedListener job:

Queue and Transaction Integration


At src/EventDispatcher.php483-492 createListenerAndJob() creates the job wrapper, then propagateListenerOptions() at src/EventDispatcher.php497-522 transfers the afterCommit setting to the job. The logic at src/EventDispatcher.php502-506:


This ensures that queued listeners respect transaction boundaries when both interfaces are present.

Sources: src/EventDispatcher.php483-522 src/CallQueuedListener.php1-139

Comparison with Event-Level Transaction Handling

FeatureEvent-Level (ShouldDispatchAfterCommit)Listener-Level (ShouldHandleEventsAfterCommit)
ScopeEntire event dispatch deferredOnly specific listeners deferred
Event ObjectMust implement interfaceNo interface required on event
Listener FlexibilityAll listeners affected equallyIndividual listeners can opt in/out
Execution TimingEvent dispatch after commitEvent dispatch immediate, handlers after commit
Checked Atdispatch() method (line 78)createClassCallable() method (line 279)
Use CaseEvent creation should wait for commitNotifications/side effects after commit

The listener-level approach provides more granular control, allowing some listeners to execute immediately while others wait for transaction completion.

Sources: src/EventDispatcher.php78-85 src/EventDispatcher.php287-292

Usage Patterns

Mixed Listener Types

You can register both immediate and post-commit listeners for the same event:


Conditional Post-Commit Behavior

The afterCommit property can be dynamically controlled:


Error Handling

Post-commit listeners that fail do not affect the database transaction, as it has already been committed. Handle errors appropriately:


Sources: src/EventDispatcher.php428-440