@commandkit/cache
CommandKit provides a powerful caching system that helps you optimize
your bot's performance by storing frequently accessed data in memory.
The @commandkit/cache
plugin allows you to cache expensive
operations like API calls and database queries, significantly
improving response times and reducing external service usage.
Installation
Install the cache package to get started:
- npm
- Yarn
- pnpm
- Bun
npm install @commandkit/cache
yarn add @commandkit/cache
pnpm add @commandkit/cache
bun add @commandkit/cache
Setup
Add the cache plugin to your CommandKit configuration:
import { defineConfig } from 'commandkit';
import { cache } from '@commandkit/cache';
export default defineConfig({
plugins: [cache()],
});
Basic usage
The simplest way to use caching is with the "use cache"
directive.
This tells CommandKit to cache the result of your function:
import type { ChatInputCommand, CommandData } from 'commandkit';
export const command: CommandData = {
name: 'weather',
description: 'Get weather information for a city',
options: [
{
name: 'city',
description: 'The city to get weather for',
type: 3, // String
required: true,
},
],
};
async function fetchWeatherData(city: string) {
'use cache';
// This expensive API call will only run once for each unique city
const response = await fetch(
`https://api.weather.com/v1/current?q=${city}`,
);
return response.json();
}
export const chatInput: ChatInputCommand = async ({
interaction,
}) => {
const city = interaction.options.getString('city', true);
const weather = await fetchWeatherData(city);
await interaction.reply(
`Weather in ${city}: ${weather.description}`,
);
};
When you call fetchWeatherData
multiple times with the same city, it
will only perform the API call once and return the cached result for
subsequent calls.
How caching works
CommandKit's caching system works by:
- Generating a cache key: Each cached function call generates a unique key based on the function's identity, arguments, and build ID
- Storing results: When a function is called, if the result isn't cached, the function executes and stores its result. If cached, it returns immediately
- Automatic cleanup: The cache system automatically removes stale entries and manages memory usage
Controlling cache behavior
Setting cache duration
Use cacheLife
to control how long entries stay in the cache:
import { cacheLife } from '@commandkit/cache';
async function fetchUserData(userId: string) {
'use cache';
// Cache for 1 hour
cacheLife('1h');
const userData = await db.users.findOne(userId);
return userData;
}
Supported time formats:
'5s'
- 5 seconds'1m'
- 1 minute'2h'
- 2 hours'1d'
- 1 day60000
- Direct milliseconds
Using cache tags
Use cacheTag
to group related cache entries for easier management:
import { cacheTag } from '@commandkit/cache';
async function fetchGuildSettings(guildId: string) {
'use cache';
// Tag this entry for easy invalidation
cacheTag(`guild:${guildId}`);
cacheTag('settings');
cacheLife('1h');
return await db.guilds.findOne(guildId);
}
Invalidating cache entries
Use revalidateTag
to invalidate specific cache entries:
import { revalidateTag } from '@commandkit/cache';
async function updateGuildSettings(guildId: string, settings: any) {
// Update the database
await db.guilds.update(guildId, settings);
// Invalidate all cached guild data
await revalidateTag(`guild:${guildId}`);
}
Common use cases
Caching API responses
async function fetchGameStats(gameId: string) {
'use cache';
cacheTag(`game:${gameId}`);
cacheLife('30m'); // API updates every 30 minutes
const response = await fetch(
`https://api.game.com/stats/${gameId}`,
);
return response.json();
}
Caching database queries
async function getUserProfile(userId: string) {
'use cache';
cacheTag(`user:${userId}`);
cacheLife('1h'); // User profiles don't change often
return await db.users.findOne({
where: { id: userId },
include: ['profile', 'settings'],
});
}
Caching computed results
async function calculateUserStats(userId: string) {
'use cache';
cacheTag(`user:${userId}`);
cacheTag('stats');
cacheLife('5m'); // Recalculate every 5 minutes
const user = await db.users.findOne(userId);
return {
level: calculateLevel(user.xp),
rank: await calculateRank(userId),
achievements: await getAchievements(userId),
};
}
Advanced configuration
Custom cache provider
For distributed caching, you can use a custom cache provider like Redis:
import { defineConfig } from 'commandkit';
import { cache, setCacheProvider } from '@commandkit/cache';
import { RedisCache } from '@commandkit/redis';
// Set up Redis as the cache provider
setCacheProvider(
new RedisCache({
host: 'localhost',
port: 6379,
}),
);
export default defineConfig({
plugins: [cache()],
});
Manual cache cleanup
Clean up stale cache entries to manage memory usage:
import { cleanup } from '@commandkit/cache';
// Clean up entries older than 24 hours
await cleanup(24 * 60 * 60 * 1000);
// Set up regular cleanup
setInterval(
async () => {
await cleanup(24 * 60 * 60 * 1000);
},
24 * 60 * 60 * 1000,
); // Run daily
The @commandkit/cache
plugin works seamlessly with other CommandKit
features and plugins. You can use it alongside the
@commandkit/redis
plugin for
distributed caching across multiple bot instances.