import json import logging import socket import threading from typing import Callable log = logging.getLogger(__name__) def _accept_loop( server_sock: socket.socket, clients: list, lock: threading.Lock, store_ref: dict, load_today: Callable | None, ) -> None: while True: try: conn, addr = server_sock.accept() log.info("Push client connected from %s", addr) with lock: store = store_ref["current"] records = store["records"] if store else [] if not records and load_today is not None: log.info("In-memory store empty — loading today's records from disk") records = load_today() try: for record in records: conn.sendall((json.dumps(record, default=str) + "\n").encode()) if records: log.info("Sent %d record(s) to %s", len(records), addr) except OSError: log.debug("Failed to send history to %s", addr) conn.close() continue clients.append(conn) except OSError: break def broadcast(snapshot: dict, clients: list, lock: threading.Lock) -> None: line = (json.dumps(snapshot, default=str) + "\n").encode() with lock: dead = [] for conn in clients: try: conn.sendall(line) except OSError: dead.append(conn) for conn in dead: clients.remove(conn) conn.close() log.info("Push client disconnected") def start_push_server( host: str, port: int, load_today: Callable | None = None, ) -> tuple: server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_sock.bind((host, port)) server_sock.listen() clients: list = [] lock = threading.Lock() store_ref: dict = {"current": None} t = threading.Thread( target=_accept_loop, args=(server_sock, clients, lock, store_ref, load_today), daemon=True, ) t.start() log.info("Push server listening on %s:%d", host, port) return clients, lock, store_ref