logo hsb.horse
← Voltar para o índice de snippets

Snippets

Supressão de Avisos com Cooldown Incorporado na Entidade

Um padrão que incorpora a lógica de supressão de avisos repetidos na própria entidade de quota. Controla adequadamente avisos frequentes como notificações de limite de taxa e alertas de cobrança.

Publicado: Atualizado:

Avisos de limites de taxa e violações de quota tendem a ocorrer repetidamente em curtos períodos de tempo. Ao incorporar a lógica de aviso e o estado de cooldown dentro da própria entidade, você pode evitar o gerenciamento global externo, garantindo que os avisos sejam emitidos apenas em intervalos apropriados.

Código

interface WarnableEntity {
/** Timestamp do último aviso (milissegundos) */
warnedAt: number | null
/** Período de cooldown do aviso (milissegundos) */
warnCooldown: number
}
/**
* Classe base para entidades com avisos baseados em cooldown
*/
class CooldownWarner<T extends WarnableEntity> {
constructor(protected entity: T) {}
/**
* Determina se um aviso deve ser emitido
*/
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
}
/**
* Emite um aviso e atualiza warnedAt
*/
protected warnBy(message: string): void {
if (!this.shouldWarn()) {
return
}
console.warn(message)
this.entity.warnedAt = Date.now()
}
}
/**
* Exemplo de implementação: entidade de limite de taxa
*/
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
})
}
/**
* Registra uma solicitação e avisa se necessário
*/
record(): void {
this.entity.current++
if (this.entity.current >= this.entity.limit) {
this.warnBy(
`Rate limit reached: ${this.entity.current}/${this.entity.limit}`
)
}
}
/**
* Reseta o contador
*/
reset(): void {
this.entity.current = 0
}
}

Uso

// Limite de 100 solicitações/min, avisar no máximo uma vez a cada 60 segundos
const limiter = new RateLimiter(100, 60_000)
// Registrar solicitações
for (let i = 0; i < 150; i++) {
limiter.record()
// Avisa na 100ª solicitação, suprimido por 60s após isso
}
// Após 1 minuto, exceder novamente acionará outro aviso
setTimeout(() => {
limiter.record() // Aviso é exibido novamente
}, 61_000)

Como Funciona

  1. A entidade possui os campos warnedAt e warnCooldown
  2. shouldWarn() compara o tempo atual com o timestamp do último aviso
  3. Retorna true se o período de cooldown passou
  4. warnBy() verifica shouldWarn() e emite um aviso apenas se a condição for atendida
  5. Após o aviso, atualiza warnedAt para iniciar o cooldown

Como a lógica de aviso e o estado estão encapsulados dentro da entidade, não há necessidade de maps ou sets globais.

Benefícios

  • Localidade: O estado do aviso é autocontido na entidade, sem necessidade de gerenciamento externo
  • Reutilizabilidade: Qualquer entidade pode implementar WarnableEntity para usar este padrão
  • Testável: Injete tempo para testar sem mocks
  • Escalável: Cada entidade mantém estado independente, amigável ao processamento concorrente

Ressalvas

A dependência direta de Date.now() significa que você precisará estender o design para injetar tempo para testes. Além disso, se as entidades forem persistidas, garanta a restauração adequada de warnedAt e a lógica de cooldown.

Aplicações

  • Notificações de aviso para limites de taxa de API
  • Alertas de violação de quota em sistemas de cobrança
  • Notificações de saldo baixo
  • Supressão de alertas de monitoramento ruidosos
  • Prevenção de rajadas em logs