Skip to main content

Tasks

A task is a state-machined unit of work tied to a single chat request.

Lifecycle

accepted → queued → running → completed|failed|cancelled

Seven states total:

StateTerminalDescription
acceptednorequest validated, task_id assigned
queuednowaiting under queue policy
runningnoactively executing lifecycle
detachednotemporarily suspended, can resume
completedyesfinished successfully
failedyesencountered an error
cancelledyesaborted by client or connection close

Transitions

Valid transitions (anything else is rejected):

accepted  → queued, running, cancelled
queued    → running, cancelled
running   → detached, completed, failed, cancelled
detached  → running, completed, failed, cancelled

Terminal states allow no further transitions. Idempotent transitions (same state → same state) are always valid.

Transition reasons

ReasonTriggerTransition
chat_acceptedRPC chat.start receivedaccepted, then queued or running
chat_startedworker begins executionrunning
chat_completedchat handler finishedcompleted
chat_failedchat handler threwfailed
abort_requestedclient sent chat.abortcancelled
connection_closedWebSocket disconnectedall active/queued → cancelled

Queue model

Per-connection serial execution — one active task at a time, others queue up.

  • max 25 queued tasks per connection (RPC_MAX_QUEUED_TASKS_PER_CONNECTION)
  • FIFO ordering, 1-indexed positions reported to client
  • aborted items marked and skipped on dequeue
  • position updates broadcast to remaining clients after abort/dequeue
  • different connections execute in parallel

Concurrency

  • one runningChatId per connection
  • runControl.shouldYield() checked during lifecycle — allows preemption for queued tasks
  • runControl.isCancelled() checked at worker start
  • global rpcQueuedTaskCount for monitoring across all connections

Storage

  • in-memory TaskStore (Map-based, not persisted across restarts)
  • max 1000 tasks by default, oldest terminal tasks evicted first
  • TaskRecord: { id, state, createdAt, updatedAt } — immutable, replaced on transition

Task vs session

  • TaskId (task_*): server-generated, one per chat request execution
  • SessionId (sess_*): client-provided, persists across requests for conversation continuity
  • one session can have many tasks over its lifetime

Key files

Further reading

  • Follow the Thread — how the trace tool went from a debugging script to a first-class CLI command