*/ public function middleware(): array { if (! Settings::bool('mail.pace.enabled', true)) { return []; } // Die Schlange am Mailable, nicht `MailLane::for(...)`: das hier ist // der Name, den `Mailable::queue()` an `pushOn()` gegeben hat — die // Spur, in der dieser Auftrag TATSÄCHLICH liegt. `MailLane::for(...)` // läge zwischen Einreihen und Abarbeiten eine Zuordnung später: würde // der Betreiber die Rechnung von ruhig auf wichtig schieben, während // zweihundert davon in der ruhigen Schlange warten, drosselte sie ab // diesem Moment das falsche Kontingent. // // `?? null` statt eines nackten Zugriffs, weil `$this->mailable` nur // die Schnittstelle zusichert: eine Mailklasse, die den Trait nicht // benutzt, hat die Eigenschaft womöglich gar nicht — und liegt dann // auch in keiner Spur, gehört also nicht gedrosselt. return match ($this->mailable->queue ?? null) { MailLane::URGENT => [new RateLimited(MailLane::URGENT)], MailLane::CALM => [new RateLimited(MailLane::CALM)], default => [], }; } /** * Sechs Stunden statt eines Versuchszählers. * * Der Arbeiter prüft `retryUntil` VOR `--tries`: liegt sie in der Zukunft, * steigt er aus, bevor er `attempts()` gegen die Versuchszahl hält. Ein * Zähler dagegen könnte nicht zwischen „dreimal zurückgelegt" und „dreimal * gescheitert" unterscheiden — die Rechnung, die am Abend zweihundertmal an * der Drossel ansteht, wäre nach dem dritten Mal endgültig gescheitert. * * Weit genug, dass auch ein Lauf über die ganze Nacht durchkommt, und eng * genug, dass eine Mail, die nach sechs Stunden noch nicht draußen ist, * nicht am nächsten Tag zwischen den neuen auftaucht. */ public function retryUntil(): DateTimeInterface { return now()->addHours(6); } }