Skip to content
GitHub

CooldownStore

class in meocord/common Since 4.1.0

abstract class CooldownStore

Where @Cooldown counts calls.

The default keeps them in memory, in this process. Bind another with @MeoCord({ cooldownStore }) so shards or several processes share one count: ShardedCooldownStore, RedisCooldownStore, or one of your own.

Examples

TypeScript
// Your database's query: trims, counts and records a key's calls in one transaction that locks the key
export abstract class CooldownQueries {
  abstract consume(key: string, uses: number, windowMs: number): Promise<CooldownVerdict>
}

@Service()
export class DatabaseCooldownStore extends CooldownStore {
  constructor(private readonly queries: CooldownQueries) { super() }

  consume(key: string, limit: CooldownLimit): Promise<CooldownVerdict> {
    return this.queries.consume(key, limit.uses, limit.windowMs)
  }
}

Members

constructor

new CooldownStore()

consume

abstract consume(key: string, limit: CooldownLimit): Promise<CooldownVerdict>

Records a call for key if the limit allows it: at most limit.uses calls within the last limit.windowMs milliseconds.

Parameters

NameTypeDescription
keystring

Identifies the handler, the cooldown and the caller, user or place it counts per.

limitCooldownLimit

The calls allowed, and the window they are counted over.

Returns

Promise<CooldownVerdict>

Whether this call was recorded, and if not, how long until one can be.

consumeMany

consumeMany(entries: readonly CooldownEntry[]): Promise<CooldownBatchVerdict>

Records a call against every entry: all of a handler's stacked cooldowns. @Cooldown calls this, once per call.

This default calls consume for each entry in order and stops at the first that refuses, so the entries before it have counted the call. Override it to check every entry and record the call against all of them only if all allow it, in one round trip: the built-in stores do, and a store behind a network should.

Parameters

NameTypeDescription
entriesreadonly CooldownEntry[]

The keys and limits the call counts against, in the order the cooldowns are declared.

Returns

Promise<CooldownBatchVerdict>

Whether the call was recorded, and if not, how long until it can be and which entry refused it.

peekMany

peekMany(_entries: readonly CooldownEntry[]): Promise<CooldownBatchVerdict>

Checks every entry as consumeMany would, and records nothing: whether a call would be allowed now. It serves a check ahead of work a refused call should not cost, such as fetching what it names from Discord; consumeMany still decides once the handler's input is ready. Cooldowns with by are never peeked, since their key comes from that input, and a key worked out before it could refuse a call consumeMany would allow.

This default allows every call, so a store without it costs no round trip and refuses only at consumeMany. Override it to answer from the store: the built-in stores do.

Parameters

NameTypeDescription
_entriesreadonly CooldownEntry[]

Returns

Promise<CooldownBatchVerdict>

Whether every entry allows a call now, and if not, how long until it would and which refused.