71 lines
2.8 KiB
PHP
71 lines
2.8 KiB
PHP
<?php
|
|
|
|
namespace App\Providers;
|
|
|
|
use App\Jobs\PacedMail;
|
|
use App\Services\Mail\MailLane;
|
|
use App\Support\Settings;
|
|
use Illuminate\Cache\RateLimiting\Limit;
|
|
use Illuminate\Mail\SendQueuedMailable;
|
|
use Illuminate\Support\Facades\RateLimiter;
|
|
use Illuminate\Support\ServiceProvider;
|
|
|
|
/**
|
|
* Der Takt der beiden gedrosselten Spuren.
|
|
*
|
|
* Die Bindung ist die ganze Verkabelung: `Mailable::newQueuedJob()` erzeugt den
|
|
* Auftrag über den Container, also fährt ab hier jede Mail über PacedMail —
|
|
* ohne dass eine Absendestelle davon weiß.
|
|
*
|
|
* `Limit::perMinutes($minuten, $anzahl)` — Minuten zuerst. Die Reihenfolge ist
|
|
* anders herum, als man sie liest, und ein vertauschtes Paar wäre ein Takt von
|
|
* fünf Mails in dreißig Minuten statt dreißig in fünf.
|
|
*
|
|
* Die direkte Spur bekommt gar keine Drossel angemeldet, nicht bloß ein hohes
|
|
* Kontingent: dort wartet gerade ein Mensch, der eben geklickt hat.
|
|
*/
|
|
class MailPaceServiceProvider extends ServiceProvider
|
|
{
|
|
public function register(): void
|
|
{
|
|
$this->app->bind(SendQueuedMailable::class, PacedMail::class);
|
|
}
|
|
|
|
public function boot(): void
|
|
{
|
|
// Die Einstellungen werden im Rückruf gelesen, nicht hier: der Rückruf
|
|
// läuft im Arbeiter je Auftrag, und eine Änderung des Betreibers wirkt
|
|
// damit ab dem nächsten Auftrag statt erst ab dem nächsten Neustart.
|
|
RateLimiter::for(MailLane::URGENT, fn () => Limit::perMinutes(
|
|
$this->mindestensEins('mail.pace.urgent.minutes', 5),
|
|
$this->mindestensEins('mail.pace.urgent.count', 30),
|
|
));
|
|
|
|
RateLimiter::for(MailLane::CALM, fn () => Limit::perMinutes(
|
|
$this->mindestensEins('mail.pace.calm.minutes', 10),
|
|
$this->mindestensEins('mail.pace.calm.count', 20),
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Eine Zahl aus den Einstellungen, mindestens eins.
|
|
*
|
|
* Die Vorgabe in `Settings::get()` greift nur bei FEHLENDER Zeile. Eine
|
|
* gespeicherte `null` — oder ein Wort statt einer Zahl — kommt als Wert
|
|
* durch und wird von `(int)` zu 0, ohne dass jemand 0 eingetippt hätte.
|
|
* Ein Kontingent von 0 hieße: `tooManyAttempts` ist immer wahr, jede Mail
|
|
* wird endlos zurückgelegt und nach sechs Stunden gesammelt zu
|
|
* `failed_jobs` — genau der Ausgang, den dieser Takt verhindern soll, nur
|
|
* über einen anderen Weg. Ein Fenster von 0 Minuten hieße umgekehrt: gar
|
|
* keine Drossel.
|
|
*
|
|
* Die Untergrenze steht hier, weil der Verlust hier passiert. Was ein
|
|
* eingetipptes 0 bedeuten SOLL, ist eine Frage an die Eingabe und gehört
|
|
* an die Konsolenseite — nicht an diese Lesestelle.
|
|
*/
|
|
private function mindestensEins(string $key, int $default): int
|
|
{
|
|
return max(1, (int) Settings::get($key, $default));
|
|
}
|
|
}
|