Send notifications and mail
The app’s queued Listener sends one notification and one Mailable after OrderPlaced commits. Its payload is an order ID and application-owned idempotency key, never an Eloquent Model; the fixture records that key before its fake delivery.
Before you begin
Run composer run reference:test:communications and review Listeners.
Handle the queued reaction
The Domain listener reacts only after the committing workflow succeeds.
examples/reference-app/app/Pulsar/Domain/Orders/Listeners/SendOrderConfirmation.php — Queued, after-commit [Domain](/concepts/domain) communication with scalar payloads.
<?php
namespace App\Pulsar\Domain\Orders\Listeners;
use App\Models\User;
use App\Pulsar\Domain\Orders\Events\OrderPlaced;
use App\Pulsar\Domain\Orders\Mail\OrderConfirmationMail;
use App\Pulsar\Domain\Orders\Models\Order;
use App\Pulsar\Domain\Orders\Notifications\OrderConfirmationNotification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Notification;
final class SendOrderConfirmation implements ShouldQueue
{
public bool $afterCommit = true;
// #region queued-order-confirmation
public function handle(OrderPlaced $event): void
{
$order = Order::query()->findOrFail($event->orderId);
$recipient = User::query()->where('tenant_id', $order->tenant_id)->firstOrFail();
$key = 'order-confirmation-'.$order->id;
if (DB::table('communication_deliveries')->insertOrIgnore([
'idempotency_key' => $key,
'created_at' => now(),
'updated_at' => now(),
]) === 0) {
return;
}
Notification::send($recipient, new OrderConfirmationNotification($order->id, $key));
Mail::to($recipient)->send(new OrderConfirmationMail($order->id, $key));
}
// #endregion
}Verify and troubleshoot
The focused test fakes mail and notifications, invokes the listener twice, and records one communication key. A crash after that local marker but before an external provider accepts the message is still a failure window; retain the same key and use provider-side deduplication where it is available.