Skip to content

Commit 79b341a

Browse files
docs(agentex): trim SSE/status comments to terse one-liners
Comment-only change; no behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 71f6b9d commit 79b341a

3 files changed

Lines changed: 9 additions & 36 deletions

File tree

agentex/src/domain/entities/tasks.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,9 @@ class TaskStatus(str, Enum):
2929
DELETED = "DELETED"
3030

3131

32-
# Canonical status partition (single source of truth for both the task-status
33-
# state machine and SSE stream termination).
34-
#
35-
# Non-terminal: a turn is in flight (RUNNING) or the task is paused and
36-
# resumable (INTERRUPTED). A task may only transition to a terminal status from
37-
# one of these. Terminal is the complement: no further events are produced and
38-
# no new turns are accepted. Defining terminal as the complement means a newly
39-
# added status is treated as terminal unless it is explicitly listed as
40-
# non-terminal here.
32+
# Canonical status partition (state machine + SSE termination).
33+
# Non-terminal: RUNNING or INTERRUPTED (resumable); terminal is the rest.
34+
# New statuses are terminal unless added to the non-terminal set.
4135
NON_TERMINAL_TASK_STATUSES = frozenset({TaskStatus.RUNNING, TaskStatus.INTERRUPTED})
4236
TERMINAL_TASK_STATUSES = frozenset(TaskStatus) - NON_TERMINAL_TASK_STATUSES
4337

agentex/src/domain/use_cases/streams_use_case.py

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -103,26 +103,12 @@ async def stream_task_events(
103103
task_id = task.id
104104

105105
stream_topic = get_task_event_stream_topic(task_id=task_id)
106-
# Snapshot the read cursor BEFORE reading task status (and before yielding
107-
# "connected"). Ordering is load-bearing for two reasons:
108-
# 1. A terminal transition writes the DB *before* it XADDs its
109-
# task_updated event. Snapshotting the tail first means that if the
110-
# status read below still says non-terminal, the terminal event (if
111-
# one is racing in) is guaranteed to land *after* this cursor, so the
112-
# live loop will read it — no missed-terminal zombie.
113-
# 2. "connected" is the client's cue to send its message, which makes
114-
# the agent start XADD-ing deltas; snapshotting after that yield
115-
# could let the first deltas advance the tail and be skipped.
116-
# Resolves to "0-0" (from the beginning) when the stream is empty.
106+
# Cursor before status read: catches a racing terminal event.
117107
last_id = await self.stream_repository.get_stream_tail_id(stream_topic)
118-
# Authoritative connect-time check. If the task is ALREADY terminal, any
119-
# terminal event sits behind the live tail and the read loop below would
120-
# never surface it — so replay whatever is buffered and end here. This
121-
# handles the late-connect case deterministically (no polling needed);
122-
# the in-loop check below handles a task that finishes while streaming.
123108
task = await self.task_service.get_task(id=task_id)
124109
# Send initial connection data
125110
yield f"data: {TaskStreamConnectedEventEntity(type='connected', taskId=task_id).model_dump_json()}\n\n"
111+
# Already terminal: replay buffered events and end (late connect).
126112
if task.status in TERMINAL_TASK_STATUSES:
127113
async for _id, data in self.read_messages(topic=stream_topic, last_id="0"):
128114
yield f"data: {data.model_dump_json()}\n\n"
@@ -158,8 +144,7 @@ async def stream_task_events(
158144
data_str = f"data: {data.model_dump_json()}\n\n"
159145
yield data_str
160146
last_message_time = asyncio.get_running_loop().time()
161-
# A terminal task_updated is always the last event
162-
# produced, so nothing follows it — end the stream here.
147+
# Terminal event is the last one — end here.
163148
if (
164149
isinstance(data, TaskStreamTaskUpdatedEventEntity)
165150
and data.task is not None
@@ -176,8 +161,7 @@ async def stream_task_events(
176161
# healthy again, so reset the backoff/error counter.
177162
consecutive_errors = 0
178163

179-
# No messages this cycle: send a keepalive ping on the
180-
# configured interval so proxies don't reap an idle stream.
164+
# Idle: send keepalive ping so proxies don't reap us.
181165
if message_count == 0:
182166
current_time = asyncio.get_running_loop().time()
183167
if current_time - last_message_time >= ping_interval:
@@ -224,9 +208,7 @@ async def stream_task_events(
224208
)
225209
yield f"data: {TaskStreamErrorEventEntity(type='error', message=str(e)).model_dump_json()}\n\n"
226210
finally:
227-
# No cleanup_stream here: the topic is shared by all viewers of the
228-
# task, so deleting it on one subscriber's exit would break the
229-
# others. The sliding TTL reclaims it instead.
211+
# Don't delete the shared topic; the TTL reclaims it.
230212
logger.info(f"SSE stream for task {task_id} has ended")
231213

232214

agentex/src/domain/use_cases/tasks_use_case.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,7 @@ async def update_mutable_fields_on_task(
137137

138138
return task_entity
139139

140-
# Statuses a task can be transitioned to a terminal status from: RUNNING is
141-
# the normal case; INTERRUPTED (paused, still-continuable) can also still be
142-
# canceled/completed/etc later. This is exactly the canonical non-terminal
143-
# set — its complement is what SSE streaming treats as terminal.
140+
# Statuses a task can transition to terminal from (the non-terminal set).
144141
_TERMINAL_TRANSITION_SOURCES = NON_TERMINAL_TASK_STATUSES
145142

146143
async def _transition_to_terminal(

0 commit comments

Comments
 (0)