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
This commit is contained in:
58
core/app/Delivery/DeliverJob.php
Normal file
58
core/app/Delivery/DeliverJob.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?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()]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user