fix(admin): defer maintenance sent_at to real delivery; read-only send-time dedup (no lost mail)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>feat/portal-design
parent
0cc5be5479
commit
28221549d1
|
|
@ -49,28 +49,27 @@ class AppServiceProvider extends ServiceProvider
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
// Send-time guard for maintenance mail (X-CP-Notification carries the
|
// Send-time guard for maintenance mail (X-CP-Notification carries the
|
||||||
// ledger id). Two things happen atomically here so exactly one copy ships
|
// ledger id). Read-only — it never marks the row sent (that happens on
|
||||||
// even if a backlog caused a duplicate job to be queued:
|
// real delivery in MessageSent, so a transport failure stays retryable).
|
||||||
// 1) suppress an announcement whose window was cancelled meanwhile;
|
// It aborts a send when the window was cancelled meanwhile, or when a
|
||||||
// 2) claim delivery with a conditional update — the first send wins,
|
// sibling copy already delivered (sent_at set) — the common backlog dedup.
|
||||||
// any duplicate finds sent_at already set and is aborted.
|
|
||||||
Event::listen(MessageSending::class, function (MessageSending $event) {
|
Event::listen(MessageSending::class, function (MessageSending $event) {
|
||||||
$header = $event->message->getHeaders()->get('X-CP-Notification');
|
$header = $event->message->getHeaders()->get('X-CP-Notification');
|
||||||
if ($header === null) {
|
if ($header === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$id = (int) $header->getBodyAsString();
|
$notification = MaintenanceNotification::query()->with('window')->find((int) $header->getBodyAsString());
|
||||||
$notification = MaintenanceNotification::query()->with('window')->find($id);
|
|
||||||
if ($notification === null) {
|
if ($notification === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if ($notification->sent_at !== null) {
|
||||||
|
return false; // already delivered — suppress a duplicate copy
|
||||||
|
}
|
||||||
if ($notification->event === 'announcement' && $notification->window?->state === 'cancelled') {
|
if ($notification->event === 'announcement' && $notification->window?->state === 'cancelled') {
|
||||||
return false; // window cancelled meanwhile — do not deliver
|
return false; // window cancelled meanwhile — do not deliver
|
||||||
}
|
}
|
||||||
|
|
||||||
$claimed = MaintenanceNotification::query()->whereKey($id)->whereNull('sent_at')->update(['sent_at' => now()]);
|
return null;
|
||||||
|
|
||||||
return $claimed === 0 ? false : null; // 0 → already delivered, suppress duplicate
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Stamp a maintenance-notification ledger row as delivered only once the
|
// Stamp a maintenance-notification ledger row as delivered only once the
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue