Skip to content

Commit e019c3b

Browse files
fix(agentex): run SSE status recheck on a timer, not only when idle
The lost-terminal-event recheck was gated on idle cycles, so steady non-terminal traffic (message_count stays nonzero) meant it never ran and a subscriber could stay open after a terminal transition whose event publish failed. Drive the recheck off its own interval timer so it fires busy or idle; the keepalive ping stays idle-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 571dfe8 commit e019c3b

1 file changed

Lines changed: 15 additions & 9 deletions

File tree

agentex/src/domain/use_cases/streams_use_case.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ async def stream_task_events(
127127
# client's read fails on each cycle; without backoff this turns into a
128128
# log-ingestion firehose (one failure per client per cycle, ~once/sec).
129129
consecutive_errors = 0
130+
last_status_check = last_message_time
130131
try:
131132
# Application-level control loop
132133
while True:
@@ -161,17 +162,22 @@ async def stream_task_events(
161162
# healthy again, so reset the backoff/error counter.
162163
consecutive_errors = 0
163164

164-
# Idle: recheck status (catches a lost terminal event), else ping.
165+
current_time = asyncio.get_running_loop().time()
166+
# Authoritative status recheck on an interval, busy or idle,
167+
# in case a terminal event's publish was lost.
168+
if current_time - last_status_check >= ping_interval:
169+
last_status_check = current_time
170+
task = await self.task_service.get_task(id=task_id)
171+
if task.status in TERMINAL_TASK_STATUSES:
172+
logger.info(
173+
f"Ending SSE stream for task {task_id}: "
174+
"terminal on status recheck"
175+
)
176+
return
177+
178+
# Idle: send keepalive ping so proxies don't reap us.
165179
if message_count == 0:
166-
current_time = asyncio.get_running_loop().time()
167180
if current_time - last_message_time >= ping_interval:
168-
task = await self.task_service.get_task(id=task_id)
169-
if task.status in TERMINAL_TASK_STATUSES:
170-
logger.info(
171-
f"Ending SSE stream for task {task_id}: "
172-
"terminal on status recheck"
173-
)
174-
return
175181
yield ":ping\n\n"
176182
last_message_time = current_time
177183
await asyncio.sleep(0.1)

0 commit comments

Comments
 (0)