Webhook küldés újrapróbálással, kétszeri küldés nélkül
A média szolgáltatásom a videófeldolgozás végén visszahívást (webhookot) küld az üzemeltető rendszernek. Ez két ok miatt nehezebb, mint elsőre tűnik: a fogadó oldal lehet éppen elérhetetlen, és a feldolgozás lépései egymástól függetlenül fejeződnek be, így ugyanaz a kész állapot többször is előállhat.
Újrapróbálás növekvő várakozással
A küldés sorban fut, legfeljebb öt próbálkozással, köztük 10 másodperc, 30 másodperc, 1 perc, majd 5 perc várakozással. Ha a válasz nem sikeres, kivételt dobok, így a sor tudja, hogy újra kell próbálnia.
Ne menjen ki kétszer
A miniatűr, a stream és az MP4 külön készül el, és mindegyik elindíthatja a küldést. Ezért a küldés előtt zárolt sort olvasok egy tranzakcióban, és beírom, hogy a küldés megtörtént. Ha már be van írva, a második job csendben kilép.
class SendVideoWebhookJob implements ShouldQueue
{
use Queueable;
public $tries = 5;
public $backoff = [10, 30, 60, 300]; // seconds to wait between attempts
public $timeout = 30;
public function handle(): void
{
// Several jobs can reach the "finished" state independently:
// only the first may send, so claim the flag under a row lock.
$shouldSend = DB::transaction(function () use ($video) {
$locked = Video::whereKey($video->id)->lockForUpdate()->first();
if (! $locked || $locked->webhook_sent_at !== null) {
return false;
}
$locked->update(['webhook_sent_at' => now()]);
return true;
});
if (! $shouldSend) {
return;
}
try {
$response = Http::timeout(10)->post($callbackUrl, $payload);
if ($response->failed()) {
throw new \RuntimeException("Webhook endpoint responded with HTTP {$response->status()}");
}
} catch (\Throwable $e) {
// Release the flag, otherwise the retry would think it was already sent.
$video->update(['webhook_sent_at' => null]);
throw $e;
}
}
}
Kivonat valódi kódból, anonimizálva.
Ha a küldés hibázik
A jelzőt a sikertelen küldés után visszaállítom, és újra dobom a kivételt. Ha ezt kihagyom, az újrapróbálás azt hinné, hogy a küldés már megvolt, és nem küldene semmit. Ezt könnyű elfelejteni, mert a hibátlan úton minden jól működik.
Hasonló problémán dolgozol?
Ha elakadtál, vagy átnéztetnéd a megoldásodat, írj, szívesen megnézem.
Írok neked →További cikkek
Nagy fájlok feltöltése megszakadás nélkül Laravelben
Hogyan oldottam meg a nagy videók feltöltését úgy, hogy egy megszakadt kérés ne vigye el az egész feltöltést.
Elolvasom →Mikor szabad újrapróbálni egy hívást?
Egy egyszerű szabály, ami megakadályozza, hogy valaki kétszer lépjen be: csak az ismételhető hívást próbáld újra.
Elolvasom →