logo hsb.horse
← Retour à l’index des snippets

Snippets

Suppression des avertissements avec cooldown intégré à l'entité

Un motif qui intègre la logique de suppression des avertissements répétés dans l'entité de quota elle-même. Contrôle correctement les avertissements fréquents tels que les notifications de limitation de débit et les alertes de facturation.

Publié: Mis à jour:

Les avertissements de limitation de débit et de dépassement de quota ont tendance à se produire de manière répétée sur de courtes périodes. En intégrant la logique d’avertissement et l’état de cooldown dans l’entité elle-même, vous pouvez éviter la gestion globale externe tout en garantissant que les avertissements ne sont émis qu’aux intervalles appropriés.

Code

interface WarnableEntity {
/** Horodatage du dernier avertissement (millisecondes) */
warnedAt: number | null
/** Période de cooldown des avertissements (millisecondes) */
warnCooldown: number
}
/**
* Classe de base pour les entités avec avertissements basés sur le cooldown
*/
class CooldownWarner<T extends WarnableEntity> {
constructor(protected entity: T) {}
/**
* Détermine si un avertissement doit être émis
*/
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
}
/**
* Émet un avertissement et met à jour warnedAt
*/
protected warnBy(message: string): void {
if (!this.shouldWarn()) {
return
}
console.warn(message)
this.entity.warnedAt = Date.now()
}
}
/**
* Exemple d'implémentation : entité de limitation de débit
*/
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
})
}
/**
* Enregistre une requête et avertit si nécessaire
*/
record(): void {
this.entity.current++
if (this.entity.current >= this.entity.limit) {
this.warnBy(
`Rate limit reached: ${this.entity.current}/${this.entity.limit}`
)
}
}
/**
* Réinitialise le compteur
*/
reset(): void {
this.entity.current = 0
}
}

Utilisation

// Limitation de 100 requêtes/min, avertir au maximum une fois toutes les 60 secondes
const limiter = new RateLimiter(100, 60_000)
// Enregistrer des requêtes
for (let i = 0; i < 150; i++) {
limiter.record()
// Avertit à la 100e requête, supprimé pendant 60s après
}
// Après 1 minute, dépasser à nouveau déclenchera un autre avertissement
setTimeout(() => {
limiter.record() // L'avertissement s'affiche à nouveau
}, 61_000)

Comment ça fonctionne

  1. L’entité possède les champs warnedAt et warnCooldown
  2. shouldWarn() compare l’heure actuelle avec l’horodatage du dernier avertissement
  3. Retourne true si la période de cooldown s’est écoulée
  4. warnBy() vérifie shouldWarn() et émet un avertissement uniquement si la condition est remplie
  5. Après l’avertissement, met à jour warnedAt pour démarrer le cooldown

La logique d’avertissement et l’état étant encapsulés dans l’entité, il n’y a pas besoin de maps ou de sets globaux.

Avantages

  • Localité : L’état d’avertissement est autonome dans l’entité, aucune gestion externe nécessaire
  • Réutilisabilité : N’importe quelle entité peut implémenter WarnableEntity pour utiliser ce motif
  • Testable : Injectez le temps pour tester sans mocks
  • Évolutif : Chaque entité maintient un état indépendant, favorable au traitement concurrent

Mises en garde

La dépendance directe à Date.now() signifie que vous devrez étendre la conception pour injecter le temps lors des tests. De plus, si les entités sont persistées, assurez-vous de restaurer correctement warnedAt et la logique de cooldown.

Applications

  • Notifications d’avertissement pour les limites de débit d’API
  • Alertes de dépassement de quota dans les systèmes de facturation
  • Notifications de solde faible
  • Suppression des alertes de surveillance bruyantes
  • Prévention des rafales dans les journaux