in-flight shows admitted/held: bare 96 with gate 2 read as broken

The counter was taken just past the GLOBAL semaphore (lifted to 96 in
auto mode so the gate is the sole limiter) but BEFORE the pool gate --
so 94 gate-queued workers counted as in-flight. The gate now pushes
its actually-admitted count and the bar shows 'admitted/held'
(e.g. in-flight 2/96 = 2 really hitting the server, 94 queued on the
gate). Verified: admitted never exceeds the gate limit.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
sora 2026-09-15 02:49:10 +00:00
parent 52547de9a3
commit dafd171d4d
2 changed files with 33 additions and 3 deletions

View File

@ -203,6 +203,18 @@ class AdaptiveGate:
except Exception:
pass
def push_inflight(self) -> None:
"""Tell the bar how many requests the gate has ACTUALLY admitted
(bar shows 'admitted/held' -- a bare held count with gate 2 read
as 'the gate is broken')."""
rep = (self.adapter.extra or {}).get('progress_reporter')
fn = getattr(rep, 'set_admitted', None)
if fn is not None:
try:
fn(self._inflight)
except Exception:
pass
# ---- gate semantics ----
async def acquire(self) -> None:
loop = asyncio.get_running_loop()
@ -230,9 +242,11 @@ class AdaptiveGate:
finally:
self._cond.release()
self._inflight += 1
self.push_inflight()
def release(self, ok: bool) -> None:
self._inflight = max(0, self._inflight - 1)
self.push_inflight()
if ok:
self._interval_ok += 1
self._level_ok += 1

View File

@ -60,6 +60,7 @@ class RichTerminalProgress:
self.started = 0.0
self.current_started = 0.0
self.inflight = 0
self.admitted = None # requests past the pool gate (None = no gate)
self.restored = 0 # checkpoint head start (drives the '+N new' marker)
self.heartbeat_task = None
@ -195,7 +196,7 @@ class RichTerminalProgress:
return
self.inflight += 1
self.current_started = time.monotonic()
self.progress.update(self.task_id, inflight=self.inflight, cur='0s')
self.progress.update(self.task_id, inflight=self._inflight_txt(), cur='0s')
def set_retries(self, n: int):
"""Show the retry count on the bar (from the adapter's attempt)."""
@ -207,6 +208,21 @@ class RichTerminalProgress:
if self.task_id is not None:
self.progress.update(self.task_id, gate=f'gate {n}')
def _inflight_txt(self) -> str:
# 'held' counts workers past the global semaphore; when a pool gate
# is active most of them are QUEUED on it -- 'admitted' is what
# actually hits the server. Showing a bare 96 with gate 2 read as
# 'the gate is not working'
if self.admitted is None:
return str(self.inflight)
return f'{self.admitted}/{self.inflight}'
def set_admitted(self, n: int):
"""Pooled runs: requests actually admitted by the gate."""
self.admitted = n
if self.task_id is not None:
self.progress.update(self.task_id, inflight=self._inflight_txt())
def rollback(self):
if self.disabled:
return
@ -214,7 +230,7 @@ class RichTerminalProgress:
just decrement the in-flight count, no success/fail bookkeeping."""
self.inflight = max(0, self.inflight - 1)
if self.task_id is not None:
self.progress.update(self.task_id, inflight=self.inflight, cur='0s')
self.progress.update(self.task_id, inflight=self._inflight_txt(), cur='0s')
def advance(self, success: bool = True):
if self.disabled:
@ -233,7 +249,7 @@ class RichTerminalProgress:
advance=1,
new=self._new_txt(completed),
rate=f"{fresh / elapsed:.2f}",
inflight=self.inflight, cur='0s',
inflight=self._inflight_txt(), cur='0s',
elapsed=_fmt(elapsed),
eta=_fmt((task.total - completed) * elapsed / fresh)
if fresh and task.total and task.total > completed else '-',