Files
fotospiel-app/app/Jobs/SendGuestPushNotificationBatch.php
2025-11-12 20:42:46 +01:00

101 lines
2.8 KiB
PHP

<?php
namespace App\Jobs;
use App\Models\GuestNotification;
use App\Models\PushSubscription;
use App\Services\Push\WebPushDispatcher;
use App\Services\PushSubscriptionService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
class SendGuestPushNotificationBatch implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
/**
* @param int[] $subscriptionIds
*/
public function __construct(
public int $notificationId,
public array $subscriptionIds
) {
$this->onQueue('notifications');
}
public function handle(
WebPushDispatcher $dispatcher,
PushSubscriptionService $subscriptions
): void {
if (! config('push.enabled')) {
return;
}
/** @var GuestNotification|null $notification */
$notification = GuestNotification::query()->find($this->notificationId);
if (! $notification) {
return;
}
/** @var Collection<int, PushSubscription> $targets */
$targets = PushSubscription::query()
->whereIn('id', $this->subscriptionIds)
->where('status', 'active')
->get();
if ($targets->isEmpty()) {
return;
}
$payload = [
'title' => $notification->title,
'body' => $notification->body,
'data' => [
'notification_id' => $notification->id,
'event_id' => $notification->event_id,
'type' => $notification->type->value,
'cta' => $notification->payload['cta'] ?? null,
],
];
foreach ($targets as $target) {
try {
$report = $dispatcher->send($target, $payload);
if ($report === null) {
continue;
}
if ($report->isSuccess()) {
$subscriptions->markDelivered($target);
continue;
}
if ($report->isSubscriptionExpired()) {
$target->update(['status' => 'revoked']);
}
$subscriptions->markFailed($target, $report->getReason());
} catch (\Throwable $exception) {
Log::channel('notifications')->warning('Web push delivery failed', [
'subscription_id' => $target->id,
'event_id' => $notification->event_id,
'reason' => $exception->getMessage(),
]);
$subscriptions->markFailed($target, $exception->getMessage());
}
}
}
}