Bug fixes

This commit is contained in:
2026-04-09 09:16:07 +02:00
parent a640615d2e
commit 3e34843292
3 changed files with 71 additions and 20 deletions
+59 -14
View File
@@ -12,17 +12,25 @@ import threading
import urllib.parse
from . import config
# Global event queue — logger pushes events, SSE endpoint streams them
_event_queue: queue.Queue = queue.Queue(maxsize=5000)
# Global event system — broadcast to all connected SSE clients
_clients: list = [] # list of queue.Queue, one per connected client
_clients_lock = threading.Lock()
_event_history: list = [] # buffer of all past events for new clients
_workdir: str = ""
_shutdown: bool = False
_server = None
def push_event(event_type: str, data: dict):
"""Push an event to all connected web clients."""
try:
_event_queue.put_nowait({"type": event_type, "data": data})
except queue.Full:
pass
msg = {"type": event_type, "data": data}
_event_history.append(msg)
with _clients_lock:
for q in _clients:
try:
q.put_nowait(msg)
except queue.Full:
pass
class WebHandler(http.server.BaseHTTPRequestHandler):
@@ -62,19 +70,28 @@ class WebHandler(http.server.BaseHTTPRequestHandler):
self.send_header("Connection", "keep-alive")
self.send_header("Access-Control-Allow-Origin", "*")
self.end_headers()
client_queue = queue.Queue(maxsize=5000)
# Replay event history for late-connecting clients
for past_event in _event_history:
client_queue.put_nowait(past_event)
with _clients_lock:
_clients.append(client_queue)
try:
while True:
while not _shutdown:
try:
event = _event_queue.get(timeout=1)
event = client_queue.get(timeout=1)
line = f"data: {json.dumps(event)}\n\n"
self.wfile.write(line.encode("utf-8"))
self.wfile.flush()
except queue.Empty:
# Send keepalive
self.wfile.write(b": keepalive\n\n")
self.wfile.flush()
except (BrokenPipeError, ConnectionResetError, OSError):
pass
finally:
with _clients_lock:
if client_queue in _clients:
_clients.remove(client_queue)
def _serve_file_tree(self):
files = []
@@ -115,14 +132,42 @@ class WebHandler(http.server.BaseHTTPRequestHandler):
self.send_error(404, "File not found or not readable")
def stop_web_server():
global _shutdown
_shutdown = True
if _server:
threading.Thread(target=_server.shutdown, daemon=True).start()
def start_web_server(port: int, workdir: str):
"""Start the web UI server in a background thread."""
"""Start the web UI server in a background daemon thread."""
global _workdir
_workdir = workdir
server = http.server.HTTPServer(("0.0.0.0", port), WebHandler)
server.daemon_threads = True
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
class ThreadedHTTPServer(http.server.HTTPServer):
allow_reuse_address = True
daemon_threads = True
def process_request(self, request, client_address):
t = threading.Thread(target=self._handle, args=(request, client_address),
daemon=True)
t.start()
def _handle(self, request, client_address):
try:
self.finish_request(request, client_address)
except Exception:
pass
try:
self.shutdown_request(request)
except Exception:
pass
server = ThreadedHTTPServer(("0.0.0.0", port), WebHandler)
global _server
_server = server
t = threading.Thread(target=server.serve_forever, daemon=True)
t.start()
return server