CluPilotCloud/app/Providers/MailPaceServiceProvider.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));
}
}