Variable: leaderboard
const leaderboard: object;
Leaderboard API for ranking and leaderboard operations
High-performance leaderboard system with intelligent caching for fast queries on large servers. Designed to handle 10k+ users with under 200ms response times.
Features:
- In-memory caching of top 100 users per guild
- Automatic cache invalidation on XP changes
- Paginated leaderboard retrieval
- Efficient rank position lookup
- Stable sort (XP desc, userId asc)
- Cache warming on first query
Caching Behavior:
- Cache TTL: 60 seconds (auto-refresh on expiry)
- Cache size: Top 100 users per guild (ranked 1-100)
- Invalidation: Automatic on xpChange, levelUp, levelDown events
- Cold start: First query builds cache (O(n log n))
- Warm cache: Subsequent queries are O(1)
Type declaration
get()
get: (guildId, offset, limit) => Promise<object> = getLeaderboardCore;
Get paginated leaderboard entries (offset, limit)
Retrieves leaderboard with pagination support and total user count. Uses cached data if available and fresh, otherwise triggers refresh. Supports deep pagination beyond the cached top N.
Complexity:
- O(1) for cached reads within cached range (within TTL)
- O(n log n) for cache refresh (all users sorted)
- O(n log n) for deep pagination fallback (full dataset sort and slice)
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
guildId | string | undefined | Guild ID |
offset | number | 0 | Starting position (0-indexed, default: 0) |
limit | number | 10 | Number of entries to return (default: 10) |
Returns
Promise<object>
Object with entries array and total user count
entries
entries: LeaderboardEntry[];
total
total: number;
Example
// Get top 10 users
const { entries, total } = await getLeaderboard('123...', 0, 10)
// Get users 11-20 (page 2)
const { entries, total } = await getLeaderboard('123...', 10, 10)
// Get users 101-110 (beyond cached top 100)
const { entries, total } = await getLeaderboard('123...', 100, 10)
getRank()
getRank: (guildId, userId) => Promise<object | null> = getUserRankCore;
Get user's rank position (1-indexed)
Gets user's rank position in the leaderboard. Returns null if user has no XP record.
For users in top 100, uses cached data (O(n) search). For users beyond cache, fetches all users and calculates position (O(n log n)). Always returns the total number of tracked users from getAllUsers.
Parameters
| Parameter | Type | Description |
|---|---|---|
guildId | string | Guild ID |
userId | string | User ID |
Returns
Promise<object | null>
Rank info (1-indexed position and total users) or null if user not found
Example
const rankInfo = await getUserRank('123...', '456...')
if (rankInfo) {
console.log(`User is rank ${rankInfo.rank} out of ${rankInfo.total}`)
}
invalidateCache()
invalidateCache: (guildId) => void = invalidateCacheCore;
Manually invalidate cache for a guild (usually automatic)
Invalidates cache for a specific guild. Called automatically when XP changes via event listeners.
Parameters
| Parameter | Type | Description |
|---|---|---|
guildId | string | Guild ID |
Returns
void
Example
// Manual cache invalidation (usually automatic)
invalidateCache('123...')
Examples
Get Top Users (Paginated)
import { leaderboard } from '@robojs/xp'
// Get top 10 users (first page)
const top10 = await leaderboard.get('guildId', 0, 10)
top10.forEach(entry => {
console.log(`#${entry.rank}: ${entry.userId} - Level ${entry.level} (${entry.xp} XP)`)
})
// Get next 10 users (second page)
const next10 = await leaderboard.get('guildId', 10, 10)
Build Leaderboard Command
import { leaderboard } from '@robojs/xp'
import { CommandInteraction } from 'discord.js'
async function handleLeaderboardCommand(interaction: CommandInteraction) {
const page = interaction.options.getInteger('page') ?? 1
const pageSize = 10
const offset = (page - 1) * pageSize
// Get leaderboard entries for this page
const entries = await leaderboard.get(interaction.guildId, offset, pageSize)
if (entries.length === 0) {
await interaction.reply('No users on this page!')
return
}
// Build leaderboard embed
const description = entries
.map(entry => `#${entry.rank}: <@${entry.userId}> - Level ${entry.level} (${entry.xp} XP)`)
.join('\n')
await interaction.reply({
embeds: [{
title: `Leaderboard - Page ${page}`,
description
}]
})
}