JeorgeC's picture
Update app.py
3ed5087 verified
import os
import threading
import time
import signal
import sys
import logging
from main import bot, app, run_bot, run_api
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Global flag to control shutdown
shutdown_flag = threading.Event()
def signal_handler(signum, frame):
"""Handle shutdown signals gracefully"""
logger.info(f"Received signal {signum}, initiating graceful shutdown...")
shutdown_flag.set()
def start_bot():
"""Start the Discord bot with error handling and restart logic"""
while not shutdown_flag.is_set():
try:
logger.info("Starting Discord bot...")
run_bot()
except Exception as e:
logger.error(f"Bot error: {e}")
if not shutdown_flag.is_set():
logger.info("Restarting bot in 5 seconds...")
time.sleep(5)
else:
break
logger.info("Bot thread shutting down.")
def start_api():
"""Start FastAPI with error handling"""
try:
logger.info("Starting FastAPI server...")
run_api()
except Exception as e:
logger.error(f"API server error: {e}")
shutdown_flag.set()
def health_monitor():
"""Monitor bot health and restart if needed"""
while not shutdown_flag.is_set():
time.sleep(30) # Check every 30 seconds
if not bot.is_ready() and not shutdown_flag.is_set():
logger.warning("Bot appears to be disconnected, but letting Discord.py handle reconnection...")
def main():
"""Main function to coordinate all services"""
# Set up signal handlers for graceful shutdown
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
logger.info("Starting Discord Flashcard Bot API...")
# Verify Discord token is present
if not os.getenv('DISCORD_BOT_TOKEN'):
logger.error("DISCORD_BOT_TOKEN environment variable not set!")
sys.exit(1)
# Start Discord bot in background thread
bot_thread = threading.Thread(target=start_bot, daemon=False, name="DiscordBot")
bot_thread.start()
logger.info("Discord bot thread started")
# Give the bot some time to initialize
time.sleep(3)
# Start health monitor
health_thread = threading.Thread(target=health_monitor, daemon=True, name="HealthMonitor")
health_thread.start()
logger.info("Health monitor thread started")
# Start FastAPI server (this will block)
try:
start_api()
except KeyboardInterrupt:
logger.info("Received keyboard interrupt")
except Exception as e:
logger.error(f"Unexpected error in main: {e}")
finally:
logger.info("Initiating shutdown...")
shutdown_flag.set()
# Wait for bot thread to finish
if bot_thread.is_alive():
logger.info("Waiting for bot thread to finish...")
bot_thread.join(timeout=10)
logger.info("Application shutdown complete")
if __name__ == "__main__":
main()