mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-10-26 17:41:58 -06:00
Require Eventlet for Engine runtime
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user