d2d.emegrendeles.hu/app/Jobs/PricelistRevertJob.php
E98Developer e338f68ee8 ADD EV3-357 Árlista feldolgozás phase5/4 visszavonás, elakadás-észlelés, kényszerlezárás
- PricelistExecutionJob + új PricelistRevertJob: $tries=1, $timeout, failed()
  hook. A service catch ága csak PHP exceptiont fog el; worker timeout vagy
  memórialimit esetén a fájl inprogress-ben ragadna, döntési gomb nélkül.
- heartbeat backstop a kill -9 esetére, ahol a failed() sem fut: minden chunk ír
  a rekordba, így az updated_at a szívverés (isExecutionStuck). Ezzel garantált,
  hogy minden kísérlet véges időn belül terminális állapotba jut - enélkül a
  kényszerlezárás sem nyílna ki soha.
- kompenzáló visszaállítás R1-R4: árak törlése, termékek visszaállítása a
  snapshotból, létrehozott termékek kivonása (soft delete, NEM fizikai törlés,
  mert lehet rájuk hivatkozás), árlista + fájl lezárása
- konfliktuskezelés: a végrehajtás óta kézzel módosított terméket kihagyjuk és
  jelentjük, nem írjuk felül vakon
- FIX phase5/3: a snapshot csak az írás ELŐTTI updated_at-et tárolta, amihez
  képest a termék a végrehajtás után mindig eltér - a konfliktus-ellenőrzés így
  minden sort kihagyott volna. Most a saját írásunk utáni updated_at is bekerül.
- kényszerlezárás: csak legalább egy terminális hibába futott visszaállítási
  kísérlet után, flag + developer szerepkör mögött, kötelező indoklással
- döntéstámogató panel: mi történt már meg az importból, hogy a felhasználó ne
  vakon válasszon a Folytatás és a Visszavonás között

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 06:36:21 +02:00

44 lines
1.2 KiB
PHP

<?php
namespace App\Jobs;
use App\Models\PricelistFile;
use App\Services\PricelistFileProcessService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Throwable;
class PricelistRevertJob implements ShouldQueue
{
use Queueable;
public int $tries = 1;
public int $timeout = 3600;
public function __construct(
public PricelistFile $pricelistFile
) {
//
}
public function handle(PricelistFileProcessService $service): void
{
$service->revert($this->pricelistFile);
}
/**
* Ugyanaz a rés, mint a végrehajtásnál - de itt nagyobb a tétje: a kényszerlezárás
* csak akkor érhető el, ha volt legalább egy TERMINÁLIS hibába futott visszaállítási
* kísérlet. Ha egy megszakadt visszaállítás inprogress-ben ragadna, a beszállító
* véglegesen blokkolva maradna, mindenféle kiút nélkül.
*/
public function failed(?Throwable $exception): void
{
app(PricelistFileProcessService::class)->failRevert(
$this->pricelistFile,
$exception?->getMessage() ?? 'A visszaállítás váratlanul megszakadt.',
);
}
}