prefix_manager ¶
Prefix management with in-memory caching for optimal performance.
This module provides efficient prefix resolution for Discord commands by maintaining an in-memory cache of guild prefixes, eliminating database hits on every message.
The PrefixManager uses a cache-first approach: 1. Check environment variable override (BOT_INFO__PREFIX) 2. Check in-memory cache (O(1) lookup) 3. Load from database on cache miss 4. Persist changes asynchronously to avoid blocking
This architecture ensures sub-millisecond prefix lookups after initial cache load.
Classes:
-
PrefixManager–Manages command prefixes with in-memory caching for optimal performance.
Classes¶
PrefixManager ¶
PrefixManager(bot: Tux)
Manages command prefixes with in-memory caching for optimal performance.
This class provides: - In-memory cache of guild prefixes - Lazy loading from database - Event-driven cache updates - Graceful fallback to default prefix - Zero database hits per message after initial load
Attributes:
-
bot(Tux) –The bot instance this manager is attached to.
-
_prefix_cache(dict[int, str]) –In-memory cache mapping guild IDs to prefixes.
-
_cache_loaded(bool) –Whether the initial cache load has completed.
-
_default_prefix(str) –Default prefix from configuration.
-
_loading_lock(Lock) –Lock to prevent concurrent cache loading.
Notes
Prefix resolution follows this priority: 1. Environment variable override (BOT_INFO__PREFIX) 2. In-memory cache (O(1) lookup) 3. Database lookup with automatic caching 4. Default prefix fallback
Initialize the prefix manager with empty cache.
Parameters:
-
bot(Tux) –The bot instance to manage prefixes for.
Methods:
-
get_prefix–Get the command prefix for a guild with automatic caching.
-
set_prefix–Set the command prefix for a guild with immediate cache update.
-
load_all_prefixes–Load all guild prefixes into cache at startup.
-
invalidate_cache–Invalidate prefix cache for a specific guild or all guilds.
-
get_cache_stats–Get cache statistics for monitoring and debugging.
Functions¶
get_prefix async ¶
Get the command prefix for a guild with automatic caching.
Resolution order: 1. Check for environment variable override 2. Check in-memory cache (O(1)) 3. Load from database and cache 4. Fallback to default prefix
Parameters:
-
guild_id(int) –The Discord guild ID.
Returns:
-
str–The command prefix for the guild, or default prefix if not found.
Notes
This method is called on every message, so it's optimized for speed. After initial cache load, this is an O(1) dictionary lookup.
set_prefix async ¶
Set the command prefix for a guild with immediate cache update.
The cache is updated immediately for instant effect, while database persistence happens asynchronously to avoid blocking command execution.
Parameters:
Notes
If prefix override is enabled via environment variable, this method will log a warning but won't update the prefix (override takes priority).
_load_guild_prefix async ¶
Load a guild's prefix from the database and cache it.
This method is called on cache misses. It ensures the guild exists in the database, loads or creates its config, and caches the result.
Parameters:
-
guild_id(int) –The Discord guild ID.
Returns:
-
str–The guild's prefix, or default prefix if loading fails.
Notes
This method always returns a prefix - it never raises. Database errors are logged and the default prefix is returned as fallback.
_persist_prefix async ¶
Persist a prefix change to the database asynchronously.
This method runs in the background after set_prefix updates the cache. If persistence fails, the cache entry is removed to maintain consistency between cache and database.
Parameters:
Notes
This method is called as a background task and never raises. Failures are logged and the cache is rolled back to maintain data consistency.
load_all_prefixes async ¶
load_all_prefixes() -> None
Load all guild prefixes into cache at startup.
This method is called once during bot initialization to populate the cache with all existing guild configurations from the database. It uses a lock to prevent concurrent loading and has built-in timeout protection.
Notes
- Uses a lock to prevent duplicate loads if called concurrently
- Has a 10-second timeout to prevent blocking startup
- Loads up to 1000 guild configs (should be more than enough)
- Marks cache as loaded even on failure to prevent retry loops
- Idempotent - safe to call multiple times
invalidate_cache ¶
invalidate_cache(guild_id: int | None = None) -> None
Invalidate prefix cache for a specific guild or all guilds.
This is useful when guild configs are updated externally or when you need to force a reload from the database.
Parameters:
-
guild_id(int | None, default:None) –The guild ID to invalidate, or None to invalidate all. Defaults to None (invalidate all).
Examples:
Invalidate a specific guild:
>>> manager.invalidate_cache(123456789)
Invalidate entire cache:
>>> manager.invalidate_cache()
get_cache_stats ¶
Get cache statistics for monitoring and debugging.
Returns:
-
dict[str, int]–Dictionary containing: - cached_prefixes: Number of guilds in cache - cache_loaded: 1 if initial load completed, 0 otherwise
Examples:
>>> stats = manager.get_cache_stats()
>>> print(f"Cached: {stats['cached_prefixes']} guilds")
Cached: 42 guilds