72 lines
2.5 KiB
PHP
72 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace App\Jobs;
|
|
|
|
use App\Models\Machine;
|
|
use App\Models\MachineEvent;
|
|
use App\Models\MachineStatusHistory;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Queue\Queueable;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class RefreshOfflineMachines implements ShouldQueue
|
|
{
|
|
use Queueable;
|
|
|
|
public function handle(): void
|
|
{
|
|
$thresholdMinutes = (int) config('laverie.machine.offline_threshold_minutes', 10);
|
|
$cutoff = now()->subMinutes($thresholdMinutes);
|
|
|
|
$machines = Machine::query()
|
|
->whereNotIn('status', ['offline', 'maintenance'])
|
|
->where(function ($query) use ($cutoff) {
|
|
$query->whereNull('last_heartbeat_at')
|
|
->orWhere('last_heartbeat_at', '<', $cutoff);
|
|
})
|
|
->get();
|
|
|
|
foreach ($machines as $machine) {
|
|
DB::transaction(function () use ($machine) {
|
|
$locked = Machine::query()->whereKey($machine->id)->lockForUpdate()->firstOrFail();
|
|
|
|
if (in_array($locked->status, ['offline', 'maintenance', 'running'], true)) {
|
|
return;
|
|
}
|
|
|
|
$thresholdMinutes = (int) config('laverie.machine.offline_threshold_minutes', 10);
|
|
$cutoff = now()->subMinutes($thresholdMinutes);
|
|
|
|
if ($locked->last_heartbeat_at !== null && $locked->last_heartbeat_at->gte($cutoff)) {
|
|
return;
|
|
}
|
|
|
|
$previousStatus = $locked->status;
|
|
$provider = config('laverie.simulation.provider_name', 'simulated');
|
|
|
|
$locked->update(['status' => 'offline']);
|
|
|
|
MachineStatusHistory::query()->create([
|
|
'machine_id' => $locked->id,
|
|
'previous_status' => $previousStatus,
|
|
'new_status' => 'offline',
|
|
'source' => 'RefreshOfflineMachines',
|
|
'reason' => 'heartbeat_timeout',
|
|
'created_at' => now(),
|
|
]);
|
|
|
|
MachineEvent::query()->create([
|
|
'machine_id' => $locked->id,
|
|
'provider' => $provider,
|
|
'event_type' => 'machine_offline',
|
|
'payload' => ['reason' => 'heartbeat_timeout'],
|
|
'occurred_at' => now(),
|
|
'received_at' => now(),
|
|
'processed_at' => now(),
|
|
'processing_status' => 'processed',
|
|
]);
|
|
});
|
|
}
|
|
}
|
|
}
|