Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f6ea43c
Add local gateway usage dashboard
huangxinV587 Nov 1, 2026
f3b5394
Mark unclean accounting runs incomplete
huangxinV587 Nov 1, 2026
627fc4c
Expand gateway monitoring and harden local rollout
huangxinV587 Nov 1, 2026
66110b5
Track session affinity and document rollout blocker
huangxinV587 Nov 1, 2026
5b65140
Clarify historical session coverage
huangxinV587 Nov 1, 2026
16ccbb8
Clarify collector status and estimated token rates
huangxinV587 Nov 1, 2026
803ed3a
Add dashboard views, stable pagination and sorting
huangxinV587 Nov 1, 2026
38803c8
Summarize observed phase speeds on dashboard
huangxinV587 Nov 1, 2026
cc0222a
Add request cache and phase-speed trends
huangxinV587 Nov 1, 2026
20a68dd
Add bounded in-process gateway usage capture
huangxinV587 Nov 1, 2026
a6816e8
Clarify observed request accounting
huangxinV587 Nov 1, 2026
fb5f44f
Use verified Caddy forwarding for in-process usage capture
huangxinV587 Nov 1, 2026
386f3aa
Reject superseded stream usage snapshots
huangxinV587 Nov 1, 2026
7f91059
Add estimated phase efficiency to dashboard
huangxinV587 Nov 1, 2026
56a6146
Name dashboard efficiency estimates by phase
huangxinV587 Nov 1, 2026
7941173
Add device group inference telemetry
huangxinV587 Nov 1, 2026
823b67b
Add cross-group telemetry and sampled history
huangxinV587 Nov 2, 2026
74d1594
Show partial device group telemetry aggregates
huangxinV587 Nov 2, 2026
772fa00
Hide stale single-group telemetry when backend is unavailable
huangxinV587 Nov 2, 2026
e452e66
Show labeled recent history when live phase samples are missing
huangxinV587 Nov 2, 2026
a99eff8
Show precise values on trend chart hover
huangxinV587 Nov 2, 2026
e22195c
Support management-port readiness probes
huangxinV587 Nov 3, 2026
eb77464
Clarify Motor readiness scope
huangxinV587 Nov 3, 2026
842bb67
Require both PD roles for Motor gateway health
huangxinV587 Nov 3, 2026
de122ed
Probe PD rank endpoints before routing
huangxinV587 Nov 3, 2026
2d22be5
Support Motor metrics and gateway usage collection
huangxinV587 Nov 5, 2026
8981ac3
Preserve Motor PD health during usage capture
huangxinV587 Nov 5, 2026
fe98626
Track speculative decoding and uncached request usage
huangxinV587 Nov 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added deploy_common/__init__.py
Empty file.
105 changes: 105 additions & 0 deletions deploy_common/reject_drain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"""Bounded, body-blind draining after an early gateway rejection."""
from contextlib import suppress
import queue
import select
import socket
import threading
import time


# Keep a full forwarding wave without exceeding Windows select()'s 512-fd set.
MAX_REJECTIONS = 480
MAX_DRAIN_BYTES = 128 * 1024 * 1024
DRAIN_TIMEOUT = 30


class RejectionDrainer:
"""Keep rejected sockets readable without holding a request admission slot."""

def __init__(self):
self._slots = threading.BoundedSemaphore(MAX_REJECTIONS)
self._pending = queue.SimpleQueue()
self._stop = threading.Event()
self._lock = threading.Lock()
self.full = 0
self.duplicate_failures = 0
self.thread = threading.Thread(target=self._run, daemon=True)
self.thread.start()

def submit(self, connection):
with self._lock:
if self._stop.is_set():
return False
if not self._slots.acquire(blocking=False):
self.full += 1
return False
duplicate = None
try:
duplicate = connection.dup()
duplicate.setblocking(False)
self._pending.put(duplicate)
return True
except OSError:
self.duplicate_failures += 1
if duplicate is not None:
duplicate.close()
self._slots.release()
return False

def close(self):
with self._lock:
self._stop.set()
self.thread.join(1)

def _run(self):
active = {}

def release(conn):
active.pop(conn, None)
conn.close()
self._slots.release()

while not self._stop.is_set():
while True:
try:
conn = self._pending.get_nowait()
except queue.Empty:
break
active[conn] = [time.monotonic() + DRAIN_TIMEOUT, MAX_DRAIN_BYTES]
if not active:
self._stop.wait(.02)
continue
try:
readable, _, failed = select.select(list(active), [], list(active), .02)
except (OSError, ValueError):
readable, failed = [], list(active)
now = time.monotonic()
for conn in set(readable + failed + [conn for conn, (deadline, _) in active.items()
if deadline <= now]):
if conn not in active:
continue
deadline, remaining = active[conn]
if conn in failed or deadline <= now:
release(conn)
continue
try:
data = conn.recv(min(65536, remaining))
except BlockingIOError:
continue
except OSError:
data = b''
remaining -= len(data)
if not data or remaining <= 0:
release(conn)
else:
active[conn][1] = remaining
for conn in list(active):
release(conn)
while True:
try:
conn = self._pending.get_nowait()
except queue.Empty:
break
with suppress(OSError):
conn.close()
self._slots.release()
Loading
Loading