RedisCooldownStore
class in meocord/common Since 4.1.0
class RedisCooldownStore extends CooldownStoreA CooldownStore on Redis, or on any server that speaks its protocol and runs its Lua scripts.
Use it for counts that outlive a restart and are shared by every process and shard on one server, so 'user' and
'global' cooldowns stay exact across them. For process shards on one host, ShardedCooldownStore needs no
database.
Examples
import { createClient } from 'redis'
const redis = await createClient({ url: process.env.REDIS_URL }).connect()
@MeoCord({
controllers: [],
clientOptions: { intents: [GatewayIntentBits.Guilds] },
cooldownStore: RedisCooldownStore.using((script, keys, args) => redis.eval(script, { keys, arguments: args })),
})
export default class App {}Members
constructor
new RedisCooldownStore(evaluate: RedisEval, options?: RedisCooldownStoreOptions)A store that runs its script through evaluate. To bind one to an app, use
RedisCooldownStore.using, which @MeoCord({ cooldownStore }) takes.
Parameters
| Name | Type | Description |
|---|---|---|
evaluate | RedisEval | Runs a script, as the client's |
options? | RedisCooldownStoreOptions | A key prefix, an |
options.prefix? | string | Put before every key the store writes. Defaults to |
options.evalsha? | RedisEvalSha | Runs the script by its SHA1, sending it in full only when the server answers |
options.hashTag? | 'handler' |
|
consume
consume(key: string, limit: CooldownLimit): Promise<CooldownVerdict>Records a call for key on the server if the limit allows it, as one script.
Parameters
| Name | Type | Description |
|---|---|---|
key | string | Identifies the handler, the cooldown and the caller, user or place it counts per. |
limit | CooldownLimit | 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 if all allow it, as one script: one round trip, however many
cooldowns a handler stacks. On Redis Cluster, where a handler's keys sit in different slots and one
script cannot reach them all, each key is counted by a script of its own, in order, and a refusal gives
back the uses counted before it, so a refused call counts against none unless a give-back fails;
hashTag: 'handler' keeps the keys in one slot, in one round trip.
Parameters
| Name | Type | Description |
|---|---|---|
entries | readonly CooldownEntry[] | The keys and limits the call counts against. |
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, recording nothing, as one read-only script: one round
trip. On Redis Cluster, where a handler's keys sit in different slots, each key is checked by a script
of its own, together; hashTag: 'handler' keeps them in one slot.
Parameters
| Name | Type | Description |
|---|---|---|
entries | readonly CooldownEntry[] | The keys and limits to check. |
Returns
Promise<CooldownBatchVerdict>Whether every entry allows a call now, and if not, how long until it would and which refused.
using
static using(
evaluate: RedisEval,
options?: RedisCooldownStoreOptions,
): new () => RedisCooldownStoreA store class for @MeoCord({ cooldownStore }) that runs its script with your client.
Parameters
| Name | Type | Description |
|---|---|---|
evaluate | RedisEval | Runs a script, as the client's |
options? | RedisCooldownStoreOptions | A key prefix, an |
options.prefix? | string | Put before every key the store writes. Defaults to |
options.evalsha? | RedisEvalSha | Runs the script by its SHA1, sending it in full only when the server answers |
options.hashTag? | 'handler' |
|
Returns
new () => RedisCooldownStoreA class the app resolves like a service, with nothing to inject.
Examples
// node-redis, sending the script by its SHA1 once the server has it
RedisCooldownStore.using((script, keys, args) => redis.eval(script, { keys, arguments: args }), {
evalsha: (sha, keys, args) => redis.evalSha(sha, { keys, arguments: args }),
})
// ioredis
RedisCooldownStore.using((script, keys, args) => redis.eval(script, keys.length, ...keys, ...args), {
prefix: 'mybot:cooldown:',
})