aa
This commit is contained in:
parent
7c3584ac71
commit
c579f3604b
@ -50,16 +50,15 @@ async def initialize_pools():
|
|||||||
current_loop = asyncio.get_event_loop() # Get the currently running event loop
|
current_loop = asyncio.get_event_loop() # Get the currently running event loop
|
||||||
|
|
||||||
# Create PostgreSQL pool with more conservative settings
|
# Create PostgreSQL pool with more conservative settings
|
||||||
# Increase max_inactive_connection_lifetime to avoid connections being closed too quickly
|
|
||||||
pg_pool = await asyncpg.create_pool(
|
pg_pool = await asyncpg.create_pool(
|
||||||
DATABASE_URL,
|
DATABASE_URL,
|
||||||
min_size=1,
|
min_size=1,
|
||||||
max_size=10,
|
max_size=10,
|
||||||
max_inactive_connection_lifetime=60.0, # 60 seconds (default is 10 minutes)
|
# max_inactive_connection_lifetime=300.0, # Using asyncpg default (600s)
|
||||||
command_timeout=30.0, # 30 seconds timeout for commands
|
command_timeout=30.0, # 30 seconds timeout for commands
|
||||||
loop=current_loop # Explicitly pass the loop
|
loop=current_loop # Explicitly pass the loop
|
||||||
)
|
)
|
||||||
log.info(f"PostgreSQL pool connected to {POSTGRES_HOST}/{POSTGRES_DB} on loop {current_loop}")
|
log.info(f"PostgreSQL pool connected to {POSTGRES_HOST}/{POSTGRES_DB} on loop {current_loop} (using default inactive connection lifetime)")
|
||||||
|
|
||||||
# Create Redis pool with connection_cls=None to avoid event loop issues
|
# Create Redis pool with connection_cls=None to avoid event loop issues
|
||||||
# This creates a connection pool that doesn't bind to a specific event loop
|
# This creates a connection pool that doesn't bind to a specific event loop
|
||||||
@ -983,13 +982,37 @@ async def get_setting(guild_id: int, key: str, default=None):
|
|||||||
# Cache miss or Redis error, get from database
|
# Cache miss or Redis error, get from database
|
||||||
log.debug(f"Cache miss for setting '{key}' (Guild: {guild_id})")
|
log.debug(f"Cache miss for setting '{key}' (Guild: {guild_id})")
|
||||||
try:
|
try:
|
||||||
async with pg_pool.acquire() as conn:
|
async with pg_pool.acquire() as conn: # Reverted to using pg_pool
|
||||||
value = await conn.fetchval(
|
value = await conn.fetchval(
|
||||||
"SELECT setting_value FROM guild_settings WHERE guild_id = $1 AND setting_key = $2",
|
"SELECT setting_value FROM guild_settings WHERE guild_id = $1 AND setting_key = $2",
|
||||||
guild_id, key
|
guild_id, key
|
||||||
)
|
)
|
||||||
|
|
||||||
final_value = value if value is not None else default
|
final_value = value if value is not None else default
|
||||||
|
except Exception as e:
|
||||||
|
log.exception(f"Database error getting setting '{key}' for guild {guild_id}: {e}")
|
||||||
|
return default # Fall back to default on database error
|
||||||
|
# finally block for db_conn removed as we are using pool context manager
|
||||||
|
|
||||||
|
# Cache the result (even if None or default, cache the absence or default value)
|
||||||
|
# Store None as a special marker, e.g., "None" string, or handle appropriately
|
||||||
|
value_to_cache = final_value if final_value is not None else "__NONE__" # Marker for None
|
||||||
|
|
||||||
|
# Try to cache the result with timeout and error handling
|
||||||
|
try:
|
||||||
|
# Use a timeout to prevent hanging on Redis operations
|
||||||
|
await asyncio.wait_for(
|
||||||
|
redis_pool.set(cache_key, value_to_cache, ex=3600), # Cache for 1 hour
|
||||||
|
timeout=2.0
|
||||||
|
)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
log.warning(f"Redis timeout setting cache for setting '{key}' for guild {guild_id}")
|
||||||
|
except RuntimeError as e:
|
||||||
|
if "got Future" in str(e) and "attached to a different loop" in str(e):
|
||||||
|
log.warning(f"Redis event loop error setting cache for setting '{key}' for guild {guild_id}: {e}")
|
||||||
|
else:
|
||||||
|
log.exception(f"Redis error setting cache for setting '{key}' for guild {guild_id}: {e}")
|
||||||
|
except Exception as e:
|
||||||
|
log.exception(f"Redis error setting cache for setting '{key}' for guild {guild_id}: {e}")
|
||||||
|
|
||||||
# Cache the result (even if None or default, cache the absence or default value)
|
# Cache the result (even if None or default, cache the absence or default value)
|
||||||
# Store None as a special marker, e.g., "None" string, or handle appropriately
|
# Store None as a special marker, e.g., "None" string, or handle appropriately
|
||||||
@ -1013,21 +1036,18 @@ async def get_setting(guild_id: int, key: str, default=None):
|
|||||||
log.exception(f"Redis error setting cache for setting '{key}' for guild {guild_id}: {e}")
|
log.exception(f"Redis error setting cache for setting '{key}' for guild {guild_id}: {e}")
|
||||||
|
|
||||||
return final_value
|
return final_value
|
||||||
except Exception as e:
|
|
||||||
log.exception(f"Database error getting setting '{key}' for guild {guild_id}: {e}")
|
|
||||||
return default # Fall back to default on database error
|
|
||||||
|
|
||||||
|
|
||||||
async def set_setting(guild_id: int, key: str, value: str | None):
|
async def set_setting(guild_id: int, key: str, value: str | None):
|
||||||
"""Sets a specific setting for a guild and updates/invalidates the cache.
|
"""Sets a specific setting for a guild and updates/invalidates the cache.
|
||||||
Setting value to None effectively deletes the setting."""
|
Setting value to None effectively deletes the setting."""
|
||||||
if not pg_pool or not redis_pool:
|
if not redis_pool: # Only redis_pool is strictly necessary for cache part now
|
||||||
log.error(f"Pools not initialized, cannot set setting '{key}'.")
|
log.error(f"Redis pool not initialized, cannot set setting '{key}' (cache part will fail).")
|
||||||
return False
|
# DB part might still work if DATABASE_URL is valid
|
||||||
|
|
||||||
cache_key = _get_redis_key(guild_id, "setting", key)
|
cache_key = _get_redis_key(guild_id, "setting", key)
|
||||||
try:
|
try:
|
||||||
async with pg_pool.acquire() as conn:
|
async with pg_pool.acquire() as conn: # Reverted to using pg_pool
|
||||||
# Ensure guild exists
|
# Ensure guild exists
|
||||||
await conn.execute("INSERT INTO guilds (guild_id) VALUES ($1) ON CONFLICT (guild_id) DO NOTHING;", guild_id)
|
await conn.execute("INSERT INTO guilds (guild_id) VALUES ($1) ON CONFLICT (guild_id) DO NOTHING;", guild_id)
|
||||||
|
|
||||||
@ -1041,8 +1061,9 @@ async def set_setting(guild_id: int, key: str, value: str | None):
|
|||||||
""",
|
""",
|
||||||
guild_id, key, str(value) # Ensure value is string
|
guild_id, key, str(value) # Ensure value is string
|
||||||
)
|
)
|
||||||
# Update cache
|
# Update cache if redis_pool is available
|
||||||
await redis_pool.set(cache_key, str(value), ex=3600)
|
if redis_pool:
|
||||||
|
await redis_pool.set(cache_key, str(value), ex=3600)
|
||||||
log.info(f"Set setting '{key}' for guild {guild_id}")
|
log.info(f"Set setting '{key}' for guild {guild_id}")
|
||||||
else:
|
else:
|
||||||
# Delete the setting if value is None
|
# Delete the setting if value is None
|
||||||
@ -1050,19 +1071,21 @@ async def set_setting(guild_id: int, key: str, value: str | None):
|
|||||||
"DELETE FROM guild_settings WHERE guild_id = $1 AND setting_key = $2",
|
"DELETE FROM guild_settings WHERE guild_id = $1 AND setting_key = $2",
|
||||||
guild_id, key
|
guild_id, key
|
||||||
)
|
)
|
||||||
# Invalidate cache
|
# Invalidate cache if redis_pool is available
|
||||||
await redis_pool.delete(cache_key)
|
if redis_pool:
|
||||||
|
await redis_pool.delete(cache_key)
|
||||||
log.info(f"Deleted setting '{key}' for guild {guild_id}")
|
log.info(f"Deleted setting '{key}' for guild {guild_id}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(f"Database or Redis error setting setting '{key}' for guild {guild_id}: {e}")
|
log.exception(f"Database or Redis error setting setting '{key}' for guild {guild_id}: {e}")
|
||||||
# Attempt to invalidate cache on error
|
# Attempt to invalidate cache on error if redis_pool is available
|
||||||
try:
|
if redis_pool:
|
||||||
await redis_pool.delete(cache_key)
|
try:
|
||||||
except Exception as redis_err:
|
await redis_pool.delete(cache_key)
|
||||||
log.exception(f"Failed to invalidate Redis cache for setting '{key}' (Guild: {guild_id}): {redis_err}")
|
except Exception as redis_err:
|
||||||
|
log.exception(f"Failed to invalidate Redis cache for setting '{key}' (Guild: {guild_id}): {redis_err}")
|
||||||
return False
|
return False
|
||||||
|
# finally block for db_conn removed as we are using pool context manager
|
||||||
|
|
||||||
# --- Cog Enablement Functions ---
|
# --- Cog Enablement Functions ---
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user