it-swarm.com.de

Abbrechen eines Jobs in der Warteschlange in Laravel oder Redis

Wie kann ich alle ausstehenden Jobs in meiner Redis-Warteschlange durchsuchen, um die Mailable mit einem bestimmten emailAddress-sendTime-Paar abzubrechen?

Ich verwende Laravel 5.5 und besitze eine Mailable, die ich wie folgt erfolgreich verwende:

$sendTime = Carbon::now()->addHours(3);
Mail::to($emailAddress)
      ->bcc([config('mail.supportTeam.address'), config('mail.main.address')])
                    ->later($sendTime, new MyCustomMailable($subject, $dataForMailView));

Wenn dieser Code ausgeführt wird, wird ein Auftrag zu meiner Redis-Warteschlange hinzugefügt.

Ich habe die Laravel -Dokumente bereits gelesen aber ich bin immer noch verwirrt.

Wie kann ich ein Mailable stornieren (das Senden verhindern)?

Ich würde gerne eine Webseite in meiner Laravel App codieren, die mir dies einfach macht.

Oder gibt es vielleicht schon Tools, die dies einfach machen (vielleicht FastoRedis?)? In diesem Fall wäre auch eine Anleitung, wie dieses Ziel auf diese Weise erreicht werden kann, sehr hilfreich. Vielen Dank!

Aktualisieren:

Ich habe versucht, die Redis-Warteschlange mit FastoRedis zu durchsuchen, aber ich kann nicht herausfinden, wie ein Mailable gelöscht werden kann. Der rote Pfeil zeigt hierher:  enter image description here

AKTUALISIEREN:

Schauen Sie sich die umfassende Antwort an, die ich unten angegeben habe .

7
Ryan

Neue umfassende Antwort:

Ich verwende jetzt meine eigene DispatchableWithControl-Eigenschaft anstelle der Dispatchable-Eigenschaft.

Ich nenne es so:

$executeAt = Carbon::now()->addDays(7)->addHours(2)->addMinutes(17);
SomeJobThatWillSendAnEmailOrDoWhatever::dispatch($contactId, $executeAt);

namespace App\Jobs;

use App\Models\Tag;
use Carbon\Carbon;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Log;

class SomeJobThatWillSendAnEmailOrDoWhatever implements ShouldQueue {

    use DispatchableWithControl,
        InteractsWithQueue,
        Queueable,
        SerializesModels;

    protected $contactId;
    protected $executeAt;

    /**
     * 
     * @param string $contactId
     * @param Carbon $executeAt
     * @return void
     */
    public function __construct($contactId, $executeAt) {
        $this->contactId = $contactId;
        $this->executeAt = $executeAt;
    }

    /**
     * Execute the job. 
     *
     * @return void
     */
    public function handle() {
        if ($this->checkWhetherShouldExecute($this->contactId, $this->executeAt)) {
            //do stuff here
        }
    }

    /**
     * The job failed to process. 
     *
     * @param  Exception  $exception
     * @return void
     */
    public function failed(Exception $exception) {
        // Send user notification of failure, etc...
        Log::error(static::class . ' failed: ' . $exception);
    }

}

namespace App\Jobs;

use App\Models\Automation;
use Carbon\Carbon;
use Illuminate\Foundation\Bus\PendingDispatch;
use Log;

trait DispatchableWithControl {

    use \Illuminate\Foundation\Bus\Dispatchable {//https://stackoverflow.com/questions/40299080/is-there-a-way-to-extend-trait-in-php
        \Illuminate\Foundation\Bus\Dispatchable::dispatch as parentDispatch;
    }

    /**
     * Dispatch the job with the given arguments.
     *
     * @return \Illuminate\Foundation\Bus\PendingDispatch
     */
    public static function dispatch() {
        $args = func_get_args();
        if (count($args) < 2) {
            $args[] = Carbon::now(TT::UTC); //if $executeAt wasn't provided, use 'now' (no delay)
        }
        list($contactId, $executeAt) = $args;
        $newAutomationArray = [
            'contact_id' => $contactId,
            'job_class_name' => static::class,
            'execute_at' => $executeAt->format(TT::MYSQL_DATETIME_FORMAT)
        ];
        Log::debug(json_encode($newAutomationArray));
        Automation::create($newAutomationArray);
        $pendingDispatch = new PendingDispatch(new static(...$args));
        return $pendingDispatch->delay($executeAt);
    }

    /**
     * @param int $contactId
     * @param Carbon $executeAt
     * @return boolean
     */
    public function checkWhetherShouldExecute($contactId, $executeAt) {
        $conditionsToMatch = [
            'contact_id' => $contactId,
            'job_class_name' => static::class,
            'execute_at' => $executeAt->format(TT::MYSQL_DATETIME_FORMAT)
        ];
        Log::debug('checkWhetherShouldExecute ' . json_encode($conditionsToMatch));
        $automation = Automation::where($conditionsToMatch)->first();
        if ($automation) {
            $automation->delete();
            Log::debug('checkWhetherShouldExecute = true, so soft-deleted record.');
            return true;
        } else {
            return false;
        }
    }

}

Nun kann ich in meiner 'Automatisierungs'-Tabelle nach ausstehenden Jobs suchen und diese Datensätze löschen (oder löschen), wenn ich die Ausführung des Jobs verhindern möchte.


Alte Antwort:

Ich habe eine neue App auf meinem Server eingerichtet und diese Weboberfläche (in einer eigenen Subdomain) zur Verwaltung meiner Redis installiert: https://github.com/ErikDubbelboer/phpRedisAdmin

Es erlaubt mir, ZSet-Schlüssel und -Werte zu bearbeiten oder zu löschen. Dies scheint zu sein, wie Laravel verzögerte Mailables in der Warteschlange gespeichert werden.

Ein anderer Ansatz, der für mich funktioniert hat, war die Installation von Redis Desktop Manager auf meinem Windows-PC.

Ich denke, ich ziehe phpRedisAdmin vor, da ich vom Web darauf zugreifen kann (mit einem beliebigen Gerät).

1
Ryan

Alle in der Warteschlange befindlichen Jobs entfernen:

Redis::command('flushdb');
5

Mach es einfacher.

Senden Sie keine E-Mail mit der späteren Option. Sie müssen einen Job mit der späteren Option absenden, und dieser Job ist für das Senden der E-Mail verantwortlich. 

Überprüfen Sie in diesem Job vor dem Senden der E-Mail das Paar emailAddress-sendTime. Wenn dies der Fall ist, senden Sie die E-Mail, wenn nicht, geben Sie "true" zurück, und die E-Mail wird nicht gesendet.

5
Sangar82

Anstatt ihn abzubrechen, können Sie ihn möglicherweise sogar aus den Redis entfernen. Aus dem, was ich in official docs über das Vergessen von command auf Redis gelesen habe, und von Laravel offiziellen Dokumenten, die mit redis interagieren, können Sie grundsätzlich anrufen Beliebiger Redis-Befehl von der Schnittstelle aus, wenn Sie den forget-Befehl aufrufen und tatsächlich node_id übergeben könnten. In diesem Fall denke ich, dass es die Nummer ist, die Sie in Ihrem Bild haben DEL 1517797158. Ich denke, Sie könnten das "Abbrechen" erreichen.

1
Nikola Gavric

Ein Ansatz kann darin bestehen, dass Ihr Job überprüft wird, um festzustellen, ob Sie eine bestimmte Adresse/Uhrzeit festgelegt haben, die gelöscht werden soll (aus der Warteschlange gelöscht). Richten Sie eine Datenbanktabelle ein oder speichern Sie einen Wert für immer mit der Adresse/Zeit in einem Array. Überprüfen Sie dann in der handle-Methode Ihres Jobs, ob etwas zum Entfernen markiert wurde, und vergleichen Sie es mit der Adresse/Zeit der zu sendenden Nachricht:

public function handle()
{
     if (Cache::has('items_to_remove')) {
         $items = Cache::get('items_to_remove');
         $removed = null;
         foreach ($items as $item) {
             if ($this->mail->to === $item['to'] && $this->mail->sendTime === $item['sendTime']) {
                  $removed = $item;
                  $this->delete();
                  break;
             }
         }
         if (!is_null($removed)) {
             $diff = array_diff($items, $removed);
             Cache::set(['items_to_remove' => $diff]);
         }
      }
  }
1
user320487

hoffe das hilft 

$connection = null;
$default = 'default';

//For the delayed jobs
var_dump( \Queue::getRedis()->connection($connection)->zrange('queues:'.$default.':delayed' ,0, -1) );

//For the reserved jobs
var_dump( \Queue::getRedis()->connection($connection)->zrange('queues:'.$default.':reserved' ,0, -1) );

$connection ist der Redis-Verbindungsname, der standardmäßig null ist, und $queue ist der Name der Warteschlange/Tube, die standardmäßig "default" ist!

quelle: https://stackoverflow.com/a/42182586/6109499

1
melsaka