feat: Enhance stream processing and SocketIO services with app context management

This commit is contained in:
JSC
2025-07-07 21:17:51 +02:00
parent e7d958eb39
commit 9ac55f8904
4 changed files with 32 additions and 55 deletions

View File

@@ -85,7 +85,7 @@ def create_app():
# Initialize stream processing service # Initialize stream processing service
from app.services.stream_processing_service import StreamProcessingService from app.services.stream_processing_service import StreamProcessingService
StreamProcessingService.initialize() StreamProcessingService.initialize(app)
# Initialize music player service # Initialize music player service
from app.services.music_player_service import music_player_service from app.services.music_player_service import music_player_service
@@ -94,7 +94,15 @@ def create_app():
music_player_service.start_vlc_instance() music_player_service.start_vlc_instance()
# Register blueprints # Register blueprints
from app.routes import admin, admin_sounds, auth, main, player, soundboard, stream from app.routes import (
admin,
admin_sounds,
auth,
main,
player,
soundboard,
stream,
)
app.register_blueprint(main.bp, url_prefix="/api") app.register_blueprint(main.bp, url_prefix="/api")
app.register_blueprint(auth.bp, url_prefix="/api/auth") app.register_blueprint(auth.bp, url_prefix="/api/auth")

View File

@@ -9,12 +9,6 @@ from app import socketio
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Add debug print to ensure this module is loaded
print(f"🔧 SocketIO Service: Module loaded, logger level: {logger.level}")
print(f"🔧 SocketIO Service: Effective logger level: {logger.getEffectiveLevel()}")
print(f"🔧 SocketIO Service: Parent logger handlers: {logger.parent.handlers}")
print(f"🔧 SocketIO Service: Logger handlers: {logger.handlers}")
class SocketIOService: class SocketIOService:
"""Service for managing SocketIO connections and user rooms.""" """Service for managing SocketIO connections and user rooms."""
@@ -102,33 +96,23 @@ class SocketIOService:
@socketio.on("connect") @socketio.on("connect")
def handle_connect(auth=None): def handle_connect(auth=None):
"""Handle client connection.""" """Handle client connection."""
print(f"🔌 CONNECT EVENT HANDLER CALLED: {request.sid}")
try: try:
logger.info(f"SocketIO connection established from {request.remote_addr}") logger.info(f"SocketIO connection established from {request.remote_addr}")
logger.info(f"Session ID: {request.sid}") logger.info(f"Session ID: {request.sid}")
logger.info(f"Cookies: {request.cookies}")
print(f"🔌 CONNECT SUCCESS: {request.sid}")
except Exception: except Exception:
logger.exception("Error handling SocketIO connection") logger.exception("Error handling SocketIO connection")
print(f"🔌 CONNECT ERROR: {request.sid}")
disconnect() disconnect()
@socketio.on("authenticate") @socketio.on("authenticate")
def handle_authenticate(data): def handle_authenticate(data):
"""Handle authentication after connection.""" """Handle authentication after connection."""
print(f"🔐 AUTHENTICATE EVENT HANDLER CALLED: {request.sid}")
logger.info(f"🔐 SOCKETIO EVENT: authenticate received from {request.sid}")
logger.info(f"🔐 Auth data: {data}")
logger.info(f"🔐 Request cookies: {dict(request.cookies)}")
try: try:
user = SocketIOService.get_user_from_socketio() user = SocketIOService.get_user_from_socketio()
logger.info(f"🔐 User lookup result: {user}")
if not user: if not user:
logger.warning("🔐 Authentication failed - no user found") logger.warning("SocketIO authentication failed - no user found")
emit("auth_error", {"error": "Authentication failed"}) emit("auth_error", {"error": "Authentication failed"})
disconnect() disconnect()
return return
@@ -139,14 +123,14 @@ def handle_authenticate(data):
# Join user-specific room # Join user-specific room
join_room(user_room) join_room(user_room)
logger.info(f"🔐 User {user_id} authenticated and joined room {user_room}") logger.info(f"User {user_id} authenticated and joined room {user_room}")
# Send current credits on authentication # Send current credits on authentication
emit("auth_success", {"user": user}) emit("auth_success", {"user": user})
emit("credits_changed", {"credits": user["credits"]}) emit("credits_changed", {"credits": user["credits"]})
except Exception: except Exception:
logger.exception("🔐 Error handling SocketIO authentication") logger.exception("Error handling SocketIO authentication")
emit("auth_error", {"error": "Authentication failed"}) emit("auth_error", {"error": "Authentication failed"})
disconnect() disconnect()
@@ -154,15 +138,13 @@ def handle_authenticate(data):
@socketio.on("test_event") @socketio.on("test_event")
def handle_test_event(data): def handle_test_event(data):
"""Test handler to verify SocketIO events are working.""" """Test handler to verify SocketIO events are working."""
print(f"🧪 TEST EVENT HANDLER CALLED: {request.sid}") logger.debug(f"Test event received: {data}")
logger.info(f"🧪 TEST EVENT received: {data}")
emit("test_response", {"message": "Test event received successfully"}) emit("test_response", {"message": "Test event received successfully"})
@socketio.on("disconnect") @socketio.on("disconnect")
def handle_disconnect(): def handle_disconnect():
"""Handle client disconnection.""" """Handle client disconnection."""
print(f"🔌 DISCONNECT EVENT HANDLER CALLED: {request.sid}")
try: try:
user = SocketIOService.get_user_from_socketio() user = SocketIOService.get_user_from_socketio()
if user: if user:
@@ -177,20 +159,3 @@ def handle_disconnect():
# Export the service instance # Export the service instance
socketio_service = SocketIOService() socketio_service = SocketIOService()
# Debug: Print registered event handlers
try:
print(f"🔧 SocketIO Service: Registered event handlers: {list(socketio.server.handlers.keys())}")
print(f"🔧 SocketIO Service: Namespace handlers: {socketio.server.handlers.get('/', {})}")
except Exception as e:
print(f"🔧 SocketIO Service: Error accessing handlers: {e}")
print(f"🔧 SocketIO Service: SocketIO server: {socketio.server}")
print(f"🔧 SocketIO Service: SocketIO instance: {socketio}")
# Test manual event registration
@socketio.on("manual_test")
def handle_manual_test(data):
"""Manual test handler."""
print(f"🧪 MANUAL TEST EVENT: {data}")
print("🔧 SocketIO Service: Manual test handler registered")

View File

@@ -30,13 +30,18 @@ class StreamProcessingService:
os.getenv("STREAM_MAX_CONCURRENT", "2") os.getenv("STREAM_MAX_CONCURRENT", "2")
) )
_downloads_dir: str = "sounds/temp" _downloads_dir: str = "sounds/temp"
_app_instance = None # Store the Flask app instance
@classmethod @classmethod
def initialize(cls) -> None: def initialize(cls, app=None) -> None:
"""Initialize the stream processing service.""" """Initialize the stream processing service."""
if cls._is_running: if cls._is_running:
return return
# Store the Flask app instance if provided
if app:
cls._app_instance = app
# Create necessary directories # Create necessary directories
os.makedirs(cls._downloads_dir, exist_ok=True) os.makedirs(cls._downloads_dir, exist_ok=True)
os.makedirs("sounds/stream", exist_ok=True) os.makedirs("sounds/stream", exist_ok=True)
@@ -83,16 +88,19 @@ class StreamProcessingService:
@classmethod @classmethod
def _worker_thread(cls) -> None: def _worker_thread(cls) -> None:
"""Worker thread for processing streams.""" """Worker thread for processing streams."""
from app import create_app
# Create app context for database operations
app = create_app()
while True: while True:
try: try:
# Get stream ID from queue with timeout # Get stream ID from queue with timeout
stream_id = cls._processing_queue.get(timeout=1) stream_id = cls._processing_queue.get(timeout=1)
# Use the stored app instance for database operations
if cls._app_instance:
with cls._app_instance.app_context():
cls._process_stream(stream_id)
else:
# Fallback: import create_app if no app instance stored
from app import create_app
app = create_app()
with app.app_context(): with app.app_context():
cls._process_stream(stream_id) cls._process_stream(stream_id)

View File

@@ -6,17 +6,13 @@ from app import create_app, socketio
# Load environment variables from .env file # Load environment variables from .env file
load_dotenv() load_dotenv()
# Configure logging to show all INFO and DEBUG messages # Configure logging
logging.basicConfig( logging.basicConfig(
level=logging.INFO, level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%H:%M:%S' datefmt='%H:%M:%S'
) )
# Set specific loggers to DEBUG for detailed SocketIO and music player logs
logging.getLogger('app.services.socketio_service').setLevel(logging.DEBUG)
logging.getLogger('app.services.music_player_service').setLevel(logging.INFO)
def main() -> None: def main() -> None:
"""Run the Flask application with SocketIO.""" """Run the Flask application with SocketIO."""