Spaces:
Running
Running
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() |