fix(pagination): Fixed socket gevent (#95)

This commit is contained in:
2025-09-23 17:06:18 +02:00
parent 572c52dada
commit 6f6d90aa60
3 changed files with 64 additions and 31 deletions

4
app.py
View File

@@ -1,6 +1,6 @@
# This need to be first
import eventlet
eventlet.monkey_patch()
import gevent.monkey
gevent.monkey.patch_all()
import logging # noqa: E402

View File

@@ -6,6 +6,8 @@ from flask_socketio import SocketIO
from .instructions import BrickInstructions
from .instructions_list import BrickInstructionsList
from .peeron_instructions import PeeronPage
from .peeron_pdf import PeeronPDF
from .set import BrickSet
from .socket_decorator import authenticated_socket, rebrickable_socket
from .sql import close as sql_close
@@ -18,6 +20,7 @@ MESSAGES: Final[dict[str, str]] = {
'CONNECT': 'connect',
'DISCONNECT': 'disconnect',
'DOWNLOAD_INSTRUCTIONS': 'download_instructions',
'DOWNLOAD_PEERON_PAGES': 'download_peeron_pages',
'FAIL': 'fail',
'IMPORT_SET': 'import_set',
'LOAD_SET': 'load_set',
@@ -70,7 +73,7 @@ class BrickSocket(object):
*args,
**kwargs,
path=app.config['SOCKET_PATH'],
async_mode='eventlet',
async_mode='gevent',
)
# Store the socket in the app config
@@ -106,6 +109,56 @@ class BrickSocket(object):
BrickInstructionsList(force=True)
@self.socket.on(MESSAGES['DOWNLOAD_PEERON_PAGES'], namespace=self.namespace) # noqa: E501
@authenticated_socket(self)
def download_peeron_pages(data: dict[str, Any], /) -> None:
logger.debug('Socket: DOWNLOAD_PEERON_PAGES={data} (from: {fr})'.format(
data=data,
fr=request.sid, # type: ignore
))
try:
# Extract data from the request
set_number = data.get('set', '')
pages_data = data.get('pages', [])
if not set_number:
raise ValueError("Set number is required")
if not pages_data:
raise ValueError("No pages selected")
# Parse set number
if '-' in set_number:
parts = set_number.split('-', 1)
set_num = parts[0]
version_num = parts[1] if len(parts) > 1 else '1'
else:
set_num = set_number
version_num = '1'
# Convert page data to PeeronPage objects
pages = []
for page_data in pages_data:
page = PeeronPage(
page_number=page_data.get('page_number', ''),
thumbnail_url=page_data.get('thumbnail_url', ''),
image_url=page_data.get('image_url', ''),
alt_text=page_data.get('alt_text', '')
)
pages.append(page)
# Create PDF generator and start download
pdf_generator = PeeronPDF(set_num, version_num, pages, socket=self)
pdf_generator.create_pdf()
# Refresh instructions list to include new PDF
BrickInstructionsList(force=True)
except Exception as e:
logger.error(f"Error in download_peeron_pages: {e}")
self.fail(message=f"Error downloading Peeron pages: {e}")
@self.socket.on(MESSAGES['IMPORT_SET'], namespace=self.namespace)
@rebrickable_socket(self)
def import_set(data: dict[str, Any], /) -> None:

36
wsgi.py
View File

@@ -1,38 +1,18 @@
#!/usr/bin/env python3
"""
WSGI entry point for BrickTracker - Production Docker deployment
This ensures proper gevent monkey patching for gunicorn
This ensures proper gevent monkey patching before any imports
"""
# CRITICAL: This must be the very first import
# CRITICAL: Monkey patch must be first, before ANY other imports
import gevent.monkey
gevent.monkey.patch_all()
import logging
import sys
import os
# Now import the regular app factory
from app import create_app
# Add the current directory to Python path
sys.path.insert(0, os.path.dirname(__file__))
# Create the application - this will be a BrickSocket instance
app_instance = create_app()
# Import Flask and BrickTracker modules directly
from flask import Flask
from bricktracker.app import setup_app
from bricktracker.socket import BrickSocket
logger = logging.getLogger(__name__)
# Create the Flask app directly (bypassing app.py to avoid double monkey patching)
app = Flask(__name__)
# Setup the app
setup_app(app)
# Create the socket
socket_instance = BrickSocket(
app,
threaded=not app.config['NO_THREADED_SOCKET'],
)
# Export the Flask app for gunicorn
application = app
# For gunicorn, we need the Flask app, not the BrickSocket wrapper
application = app_instance.app if hasattr(app_instance, 'app') else app_instance