logo hsb.horse
← Zur Snippets-Übersicht

Snippets

In Entität eingebettete Cooldown-Warnungsunterdrückung

Ein Muster, das die Logik zur Unterdrückung wiederholter Warnungen in die Quota-Entität selbst einbettet. Kontrolliert häufige Warnungen wie Ratenlimit-Benachrichtigungen und Abrechnungswarnungen angemessen.

Veröffentlicht: Aktualisiert:

Warnungen für Ratenlimits und Quota-Überschreitungen treten häufig in kurzen Zeitspannen wiederholt auf. Durch Einbetten der Warnlogik und des Cooldown-Status in die Entität selbst können Sie eine externe globale Verwaltung vermeiden und gleichzeitig sicherstellen, dass Warnungen nur in angemessenen Intervallen ausgegeben werden.

Code

interface WarnableEntity {
/** Zeitstempel der letzten Warnung (Millisekunden) */
warnedAt: number | null
/** Cooldown-Zeitraum für Warnungen (Millisekunden) */
warnCooldown: number
}
/**
* Basisklasse für Entitäten mit Cooldown-basierten Warnungen
*/
class CooldownWarner<T extends WarnableEntity> {
constructor(protected entity: T) {}
/**
* Ermittelt, ob eine Warnung ausgegeben werden soll
*/
protected shouldWarn(): boolean {
const now = Date.now()
if (this.entity.warnedAt === null) {
return true
}
const elapsed = now - this.entity.warnedAt
return elapsed >= this.entity.warnCooldown
}
/**
* Gibt eine Warnung aus und aktualisiert warnedAt
*/
protected warnBy(message: string): void {
if (!this.shouldWarn()) {
return
}
console.warn(message)
this.entity.warnedAt = Date.now()
}
}
/**
* Beispielimplementierung: Ratenlimit-Entität
*/
interface RateLimitEntity extends WarnableEntity {
limit: number
current: number
}
class RateLimiter extends CooldownWarner<RateLimitEntity> {
constructor(limit: number, cooldown: number = 60_000) {
super({
limit,
current: 0,
warnedAt: null,
warnCooldown: cooldown
})
}
/**
* Zeichnet eine Anfrage auf und warnt bei Bedarf
*/
record(): void {
this.entity.current++
if (this.entity.current >= this.entity.limit) {
this.warnBy(
`Rate limit reached: ${this.entity.current}/${this.entity.limit}`
)
}
}
/**
* Setzt den Zähler zurück
*/
reset(): void {
this.entity.current = 0
}
}

Verwendung

// 100 Anfragen/Min Ratenlimit, höchstens einmal alle 60 Sekunden warnen
const limiter = new RateLimiter(100, 60_000)
// Anfragen aufzeichnen
for (let i = 0; i < 150; i++) {
limiter.record()
// Warnt bei der 100. Anfrage, danach 60s lang unterdrückt
}
// Nach 1 Minute löst erneutes Überschreiten eine weitere Warnung aus
setTimeout(() => {
limiter.record() // Warnung wird erneut angezeigt
}, 61_000)

Funktionsweise

  1. Die Entität verfügt über die Felder warnedAt und warnCooldown
  2. shouldWarn() vergleicht die aktuelle Zeit mit dem letzten Warnungszeitstempel
  3. Gibt true zurück, wenn die Cooldown-Periode abgelaufen ist
  4. warnBy() prüft shouldWarn() und gibt eine Warnung nur aus, wenn die Bedingung erfüllt ist
  5. Nach der Warnung aktualisiert es warnedAt, um den Cooldown zu starten

Da die Warnlogik und der Status in der Entität gekapselt sind, sind keine globalen Maps oder Sets erforderlich.

Vorteile

  • Lokalität: Der Warnungsstatus ist in der Entität enthalten, keine externe Verwaltung erforderlich
  • Wiederverwendbarkeit: Jede Entität kann WarnableEntity implementieren, um dieses Muster zu verwenden
  • Testbar: Injizieren Sie Zeit zum Testen ohne Mocks
  • Skalierbar: Jede Entität pflegt einen unabhängigen Status, freundlich zur nebenläufigen Verarbeitung

Vorsichtsmaßnahmen

Die direkte Abhängigkeit von Date.now() bedeutet, dass Sie das Design erweitern müssen, um Zeit für Tests zu injizieren. Wenn Entitäten persistiert werden, stellen Sie außerdem die ordnungsgemäße Wiederherstellung von warnedAt und die Cooldown-Logik sicher.

Anwendungen

  • Warnungsbenachrichtigungen für API-Ratenlimits
  • Quota-Überschreitungswarnungen in Abrechnungssystemen
  • Benachrichtigungen bei niedrigem Guthaben
  • Unterdrückung lauter Überwachungswarnungen
  • Burst-Verhinderung bei der Protokollierung