Require Eventlet for Engine runtime

This commit is contained in:
2025-10-26 02:09:44 -06:00
parent 1b6d015124
commit ccf2e63620

View File

@@ -9,6 +9,7 @@ error log) to align with the project's operational practices.
""" """
from __future__ import annotations from __future__ import annotations
import importlib.util
import logging import logging
import ssl import ssl
import sys import sys
@@ -16,72 +17,74 @@ from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Any, Mapping, Optional, Sequence, Tuple from typing import Any, Mapping, Optional, Sequence, Tuple
try: # pragma: no-cover - optional dependency when running without eventlet
import eventlet # type: ignore
except Exception: # pragma: no-cover - fall back to threading mode
eventlet = None # type: ignore[assignment]
logging.getLogger(__name__).warning(
"Eventlet is not available; Engine will run Socket.IO in threading mode."
)
else: # pragma: no-cover - monkey patch only when eventlet is present
eventlet.monkey_patch(thread=False)
from flask import Flask, request def _require_dependency(module: str, friendly_name: str) -> None:
from flask_cors import CORS if importlib.util.find_spec(module) is None: # pragma: no cover - import check
from flask_socketio import SocketIO raise RuntimeError(
from werkzeug.middleware.proxy_fix import ProxyFix f"{friendly_name} (Python module '{module}') is required for the Borealis Engine runtime. "
"Install the packaged dependencies by running Borealis.ps1 or ensure the module is present in the active environment."
)
if eventlet:
try: # pragma: no-cover - defensive import mirroring the legacy runtime.
from eventlet.wsgi import HttpProtocol # type: ignore
except Exception: # pragma: no-cover - the Engine should still operate without it.
HttpProtocol = None # type: ignore[assignment]
else:
_original_handle_one_request = HttpProtocol.handle_one_request
def _quiet_tls_http_mismatch(self): # type: ignore[override] _require_dependency("eventlet", "Eventlet")
"""Mirror the legacy suppression of noisy TLS handshake errors.""" _require_dependency("flask", "Flask")
_require_dependency("flask_socketio", "Flask-SocketIO")
def _close_connection_quietly(): import eventlet # type: ignore # noqa: E402 # pragma: no cover - import guarded above
try: from eventlet import wsgi as eventlet_wsgi # type: ignore # noqa: E402 # pragma: no cover
self.close_connection = True # type: ignore[attr-defined]
except Exception:
pass
try:
conn = getattr(self, "socket", None) or getattr(self, "connection", None)
if conn:
conn.close()
except Exception:
pass
from flask import Flask, request # noqa: E402
from flask_cors import CORS # noqa: E402
from flask_socketio import SocketIO # noqa: E402
from werkzeug.middleware.proxy_fix import ProxyFix # noqa: E402
eventlet.monkey_patch(thread=False) # pragma: no cover - aligns with legacy runtime
HttpProtocol = getattr(eventlet_wsgi, "HttpProtocol", None)
if HttpProtocol is not None: # pragma: no branch - attribute exists in supported versions
_original_handle_one_request = HttpProtocol.handle_one_request
def _quiet_tls_http_mismatch(self): # type: ignore[override]
"""Mirror the legacy suppression of noisy TLS handshake errors."""
def _close_connection_quietly():
try: try:
return _original_handle_one_request(self) self.close_connection = True # type: ignore[attr-defined]
except ssl.SSLError as exc: # type: ignore[arg-type] except Exception:
reason = getattr(exc, "reason", "") pass
reason_text = str(reason).lower() if reason else "" try:
message = " ".join(str(arg) for arg in exc.args if arg).lower() conn = getattr(self, "socket", None) or getattr(self, "connection", None)
if ( if conn:
"http_request" in message conn.close()
or reason_text == "http request" except Exception:
or "unknown ca" in message pass
or reason_text == "unknown ca"
or "unknown_ca" in message try:
): return _original_handle_one_request(self)
_close_connection_quietly() except ssl.SSLError as exc: # type: ignore[arg-type]
return None reason = getattr(exc, "reason", "")
raise reason_text = str(reason).lower() if reason else ""
except ssl.SSLEOFError: message = " ".join(str(arg) for arg in exc.args if arg).lower()
_close_connection_quietly() if (
return None "http_request" in message
except ConnectionAbortedError: or reason_text == "http request"
or "unknown ca" in message
or reason_text == "unknown ca"
or "unknown_ca" in message
):
_close_connection_quietly() _close_connection_quietly()
return None return None
raise
except ssl.SSLEOFError:
_close_connection_quietly()
return None
except ConnectionAbortedError:
_close_connection_quietly()
return None
HttpProtocol.handle_one_request = _quiet_tls_http_mismatch # type: ignore[assignment] HttpProtocol.handle_one_request = _quiet_tls_http_mismatch # type: ignore[assignment]
else:
HttpProtocol = None # type: ignore[assignment]
_SOCKETIO_ASYNC_MODE = "eventlet" if eventlet else "threading" _SOCKETIO_ASYNC_MODE = "eventlet"
# Ensure the legacy ``Modules`` package is importable when running from the # Ensure the legacy ``Modules`` package is importable when running from the