Push last snapshot immediately to newly connected clients
The server keeps the most recent snapshot in memory (under the same lock as the client list). When a client connects it receives that snapshot right away, then continues to receive live updates on each collection cycle. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -95,7 +95,7 @@ def run(args: argparse.Namespace) -> None:
|
|||||||
logs_dir.mkdir(exist_ok=True)
|
logs_dir.mkdir(exist_ok=True)
|
||||||
out = auto_out_path(logs_dir, vin)
|
out = auto_out_path(logs_dir, vin)
|
||||||
|
|
||||||
push_clients, push_lock = network.start_push_server(args.host, args.port)
|
push_clients, push_lock, push_last = network.start_push_server(args.host, args.port)
|
||||||
|
|
||||||
current_day = datetime.now(timezone.utc).date()
|
current_day = datetime.now(timezone.utc).date()
|
||||||
store = load_store(out, vin, args.interval)
|
store = load_store(out, vin, args.interval)
|
||||||
@@ -121,7 +121,7 @@ def run(args: argparse.Namespace) -> None:
|
|||||||
snapshot = collect_snapshot(vehicle, domains)
|
snapshot = collect_snapshot(vehicle, domains)
|
||||||
store["records"].append(snapshot)
|
store["records"].append(snapshot)
|
||||||
save_store(out, store, args.max_records)
|
save_store(out, store, args.max_records)
|
||||||
network.broadcast(snapshot, push_clients, push_lock)
|
network.broadcast(snapshot, push_clients, push_lock, push_last)
|
||||||
log.info("Record #%d saved at %s", len(store["records"]), snapshot["ts"])
|
log.info("Record #%d saved at %s", len(store["records"]), snapshot["ts"])
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise
|
raise
|
||||||
|
|||||||
+18
-3
@@ -10,20 +10,30 @@ def _accept_loop(
|
|||||||
server_sock: socket.socket,
|
server_sock: socket.socket,
|
||||||
clients: list,
|
clients: list,
|
||||||
lock: threading.Lock,
|
lock: threading.Lock,
|
||||||
|
last_snapshot: dict,
|
||||||
) -> None:
|
) -> None:
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
conn, addr = server_sock.accept()
|
conn, addr = server_sock.accept()
|
||||||
log.info("Push client connected from %s", addr)
|
log.info("Push client connected from %s", addr)
|
||||||
with lock:
|
with lock:
|
||||||
|
if last_snapshot["data"] is not None:
|
||||||
|
try:
|
||||||
|
line = (json.dumps(last_snapshot["data"], default=str) + "\n").encode()
|
||||||
|
conn.sendall(line)
|
||||||
|
except OSError:
|
||||||
|
log.debug("Failed to send initial snapshot to %s", addr)
|
||||||
|
conn.close()
|
||||||
|
continue
|
||||||
clients.append(conn)
|
clients.append(conn)
|
||||||
except OSError:
|
except OSError:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
def broadcast(snapshot: dict, clients: list, lock: threading.Lock) -> None:
|
def broadcast(snapshot: dict, clients: list, lock: threading.Lock, last_snapshot: dict) -> None:
|
||||||
line = (json.dumps(snapshot, default=str) + "\n").encode()
|
line = (json.dumps(snapshot, default=str) + "\n").encode()
|
||||||
with lock:
|
with lock:
|
||||||
|
last_snapshot["data"] = snapshot
|
||||||
dead = []
|
dead = []
|
||||||
for conn in clients:
|
for conn in clients:
|
||||||
try:
|
try:
|
||||||
@@ -43,7 +53,12 @@ def start_push_server(host: str, port: int) -> tuple:
|
|||||||
server_sock.listen()
|
server_sock.listen()
|
||||||
clients: list = []
|
clients: list = []
|
||||||
lock = threading.Lock()
|
lock = threading.Lock()
|
||||||
t = threading.Thread(target=_accept_loop, args=(server_sock, clients, lock), daemon=True)
|
last_snapshot: dict = {"data": None}
|
||||||
|
t = threading.Thread(
|
||||||
|
target=_accept_loop,
|
||||||
|
args=(server_sock, clients, lock, last_snapshot),
|
||||||
|
daemon=True,
|
||||||
|
)
|
||||||
t.start()
|
t.start()
|
||||||
log.info("Push server listening on %s:%d", host, port)
|
log.info("Push server listening on %s:%d", host, port)
|
||||||
return clients, lock
|
return clients, lock, last_snapshot
|
||||||
Reference in New Issue
Block a user