Skip to content

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

Python
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
Python
get_prefix(guild_id: int) -> str

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
Python
set_prefix(guild_id: int, prefix: str) -> None

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:

  • guild_id (int) –

    The Discord guild ID.

  • prefix (str) –

    The new command prefix to set.

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
Python
_load_guild_prefix(guild_id: int) -> str

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
Python
_persist_prefix(guild_id: int, prefix: str) -> None

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:

  • guild_id (int) –

    The Discord guild ID.

  • prefix (str) –

    The prefix to persist.

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
Python
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
Python
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:

Python Console Session
>>> manager.invalidate_cache(123456789)

Invalidate entire cache:

Python Console Session
>>> manager.invalidate_cache()
get_cache_stats
Python
get_cache_stats() -> dict[str, int]

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:

Python Console Session
>>> stats = manager.get_cache_stats()
>>> print(f"Cached: {stats['cached_prefixes']} guilds")
Cached: 42 guilds

Functions