Files
hado/core/app/Delivery/DeliverJob.php
nikita.hohlov affac4ce1a feat: tick planner, delivery job, scheduler and purge
Also: test uses disabled channels instead of deleting them (FK cascade); ChannelRegistry no longer final so tests can extend it (controller ruling).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BCrwHHnGCB5XH968Nxokqw
2026-09-04 07:38:16 -03:00

59 lines
1.7 KiB
PHP

<?php
namespace App\Delivery;
use App\Channels\ChannelRegistry;
use App\Enums\DeliveryResult;
use App\Models\Delivery;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Throwable;
final class DeliverJob implements ShouldQueue
{
use Queueable;
public int $tries = 3;
public function __construct(public readonly int $deliveryId) {}
/** @return list<int> */
public function backoff(): array
{
return [30, 120, 600];
}
public function handle(ChannelRegistry $registry): void
{
$delivery = Delivery::with(['event.user', 'event.source', 'channel'])->findOrFail($this->deliveryId);
if ($delivery->result !== DeliveryResult::Pending) {
return;
}
if ($delivery->event->isTerminal()) {
$delivery->update(['result' => DeliveryResult::Failed, 'error' => 'skipped: событие уже закрыто']);
return;
}
$outcome = $registry->for($delivery->channel->type)
->deliver($delivery->event, $delivery->event->user, $delivery->channel->config, $delivery);
if ($outcome->ok) {
$delivery->update(['result' => DeliveryResult::Ok, 'sent_at' => now(), 'error' => null, 'meta' => $outcome->meta]);
return;
}
$delivery->update(['error' => $outcome->error]);
throw new DeliveryFailed($outcome->error ?? 'delivery failed');
}
public function failed(Throwable $e): void
{
Delivery::whereKey($this->deliveryId)
->where('result', DeliveryResult::Pending->value)
->update(['result' => DeliveryResult::Failed, 'error' => $e->getMessage()]);
}
}