feat: Enhance stream processing and SocketIO services with app context management
This commit is contained in:
@@ -85,16 +85,24 @@ 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
|
||||||
|
|
||||||
music_player_service.app = app # Store app instance for Flask context
|
music_player_service.app = app # Store app instance for Flask context
|
||||||
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")
|
||||||
|
|||||||
@@ -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")
|
|
||||||
|
|||||||
@@ -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,18 +88,21 @@ 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)
|
||||||
|
|
||||||
with app.app_context():
|
# Use the stored app instance for database operations
|
||||||
cls._process_stream(stream_id)
|
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():
|
||||||
|
cls._process_stream(stream_id)
|
||||||
|
|
||||||
cls._processing_queue.task_done()
|
cls._processing_queue.task_done()
|
||||||
|
|
||||||
|
|||||||
6
main.py
6
main.py
@@ -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."""
|
||||||
|
|||||||
Reference in New Issue
Block a user