2017-10-25 1 views
1

Ich frage mich, wie ich damit umgehen soll. Ich habe einen Webhook-Endpunkt, der auf einen Webhook-Anruf von Github reagiert.Antwort senden, aber Skript lange laufen lassen, um Timeout zu verhindern?

Es startet einen lang andauernden Prozess, in dem es das Repository klont, von dem der Webhook-Aufruf gemacht wurde.

/** 
* The webhook endpoint. 
* 
* @param Request $request 
* @return mixed 
* @throws \Exception 
*/ 
public function webhook(Request $request) 
{ 
    // The type of GitHub event that we receive. 
    $event = $request->header('X-GitHub-Event'); 

    $url = $this->createCloneUrl(); 
    $this->cloneGitRepo($url); 

    return new Response('Webhook received succesfully', 200); 
} 

Das Problem dabei ist, dass Github einen Fehler gibt, wenn die Antwort nicht schnell genug zur Verfügung gestellt wird.

Wir könnten diese Nutzlast nicht liefern: Service-Timeout

Dies ist zu Recht so, weil meine cloneGitRepo Methode einfach ist die Ausführung der Reaktion blockiert und es dauert zu lange.

Wie kann ich immer noch eine Antwort liefern, um Github zu bestätigen, dass der Webhook-Aufruf erfolgreich durchgeführt wurde und mein lang andauernder Prozess gestartet wurde?

Ich benutze Laravel für all dies mit Redis, vielleicht kann dort etwas erreicht werden? Ich bin offen für alle Vorschläge.

+0

Sie verwenden sollten [Queues] (https: // Laravel .com/docs/5.5/Warteschlangen) – ljubadr

+1

Mit Docs __Queues können Sie die Verarbeitung einer zeitaufwendigen Aufgabe verzögern, z. B. das Senden einer E-Mail, bis zu einem späteren Zeitpunkt. Wenn Sie diese zeitaufwendigen Aufgaben verschieben, werden die Webanfragen für Ihre Anwendung drastisch beschleunigt. __ – ljubadr

+1

Oder Sie können [Asynchrone Prozesse ausführen] (https://symfony.com/doc/current/components/process.html#running-processes-asynchronous) verwenden), da die 'Symfony \ Component \ Process \ Process' bereits von Laravel enthalten ist ... – ljubadr

Antwort

1

Was Sie suchen, ist ein Job in der Warteschlange. Laravel macht dies sehr einfach mit Laravel Queues.

Mit Warteschlangen richten Sie einen Warteschlangentreiber ein (Datenbank, Redis, Amazon SQS usw.), und dann haben Sie einen oder mehrere Warteschlangen-Worker, die kontinuierlich ausgeführt werden. Wenn Sie einen Job in die Warteschlange von Ihrer webhook-Methode einfügen, wird er von einem Ihrer Warteschlangenarbeiter abgeholt und in einem separaten Prozess ausgeführt. Die Aufgabe, einen in die Warteschlange eingereihten Job an eine Warteschlange zu senden, ist jedoch sehr schnell, sodass Ihre Methode webhook schnell zurückkehrt, während die tatsächliche Arbeit vom Warteschlangen-Worker ausgeführt wird.

Die verknüpfte Dokumentation enthält alle Details, aber der allgemeine Prozess wird sein:

  1. Einrichten einer Warteschlange Verbindung. Sie erwähnen, dass Sie Redis bereits verwenden, ich würde damit beginnen.

  2. Verwenden Sie php artisan make:job CloneGitRepo, um eine CloneGitRepo Jobklasse zu erstellen.

    • Es soll den Illuminate\Contracts\Queue\ShouldQueue-Schnittstelle implementieren, so dass Laravel kennt diesen Auftrag an eine Warteschlange zu senden, wenn es geschickt wird.

    • Stellen Sie sicher, dass Eigenschaften für alle Daten definiert werden, die Sie an den Konstruktor übergeben. Dies ist erforderlich, damit der Worker den Job ordnungsgemäß wiederherstellen kann, wenn er aus der Warteschlange entfernt wird.

    • Der Warteschlangenmitarbeiter ruft die handle()-Methode zur Verarbeitung des Jobs auf. Alle Abhängigkeiten können hier angegeben werden und sie werden aus dem IoC-Container injiziert.

  3. den Auftrag an die Warteschlange zu versenden, können Sie entweder die globale dispatch() Helferfunktion, oder rufen Sie sich die statische dispatch() Methode bei der Arbeit verwenden.

    • dispatch(new CloneGitRepo($url));

    • CloneGitRepo::dispatch($url);

Also, Ihr Webhook aussehen würde:

public function webhook(Request $request) 
{ 
    // The type of GitHub event that we receive. 
    $event = $request->header('X-GitHub-Event'); 

    $url = $this->createCloneUrl(); 

    CloneGitRepo::dispatch($url); 

    return new Response('Webhook received succesfully', 200); 
} 
+0

Stellen Sie außerdem sicher, dass Sie Ihre '.env' aktualisieren, um den richtigen Warteschlangentreiber zu verwenden, da Sie ansonsten keine Ausgabe und keine Möglichkeit zum Debuggen erhalten. Danke für deine Antwort! –

Verwandte Themen