Skip to Content
概念狀態機與輪詢

狀態機與輪詢

沒有 streaming。 前端用輪詢(GET 狀態)追蹤進度。以下是各資源的狀態值(取自 src/schemas/enums.py)與轉換。

環境版本 SandboxEnvironmentVersionState

draft → build_queued → building → quarantined → verifying → verified → regional_provisioning → ready ← 可被 Task Version 引用

分支/失敗狀態:retryable_failed、rejected、abandoned、blocked、superseded、archived、provisioning_blocked。quarantined 不是失敗狀態——它是成功路徑上的必經一站:compose(建置)成功後版本一定先進 quarantined,掃描階段開始才轉 verifying。

  • retryable_failed → POST /.../retry-build。
  • provisioning_blocked / provisioning 失敗 → POST /.../retry-provisioning。

建置嘗試 SandboxBuildAttemptState

validation_queued → validating → build_queued → building → verifying → completed 取消:cancel_requested → cancelling → cancelled 失敗:customer_failed / platform_failed
  • terminal_class ∈ completed / customer_failed / platform_failed / cancelled。
  • error_code / stage_code / phase 提供細節;report_total_bytes > 0 表示有建置報告。常見 error_code:policy_reject(客戶)、identity_config、tenant_cancel(CVE 掃描結果自 2026-08-25 起只是參考——vulnerability_reject 已經不會再出現)。
  • 取消不是同一請求內結算。 POST .../builds/{id}/cancel 圍欄 attempt(cancel_requested)並寫入可持久化的 provider-cancel intent,即使 attempt 還在排隊。輪詢到 terminal_class=cancelled。在 cancel_requested/cancelling 再取消一次是冪等。

執行 SandboxRunState

queued → starting → running → completed 取消:cancel_requested → cancelled 失敗:customer_failed / platform_failed
  • 終態以 terminal_at 標記。
  • error_code 提供失敗原因。

任務版本 SandboxTaskVersionState

draft → published → archived

另有 content_state:active(可跑)或 scrubbed(保留期/offboarding 後內容被清掉)。選單/可執行判斷要求 state == "published" 且 content_state == "active"。

環境父層 state:active → archived。Binding 活著的 state:enabled(選單還要 authority_applicable)。Share grant 退休:revoked。

Agent 提案 SandboxProposalState(Agent 確認流程)

prepared → committing → committed 其他:superseded(被更新提案取代)/ cancelled / expired / failed

詳見 Agent 確認流程。

輪詢建議

  • 建置:輪詢 GET /environments/{id}/versions/{vid}/builds/{attempt_id},直到 terminal_class 有值。
  • 執行:輪詢 GET /chatrooms/{id}/runs/{run_id},直到 terminal_at 有值。
  • REST 建議間隔:2 秒,約 30 秒後退避到 10 秒,看到 terminal_at/terminal_class 就停。MAX_STATUS_WAIT_SECONDS = 60 只是 agent 工具 sandbox_job_status.wait_seconds 上限,不是 REST long-poll。
  • 通知:SandboxNotificationEvent(見 通知)可以叫醒 UI;不改變上面的輪詢模型。一定要再 GET。

取消(runs)

  • 未認領(queued/尚未派送):POST .../cancel 立刻設成 cancelled,釋放定價 hold,佇列 lease 標 released——自 2026-08-30 起,佇列/併發容量 slot 也會立刻釋放(之前若碰上競態的併發派工,可能讓已取消的 run 卡住佔著 slot)。
  • 已認領/執行中:設成 cancel_requested,寫入耐久 cancel outbox;runner 再走到 cancelled。
  • 租戶取消圍欄贏過 runner executions/complete 時,公開 error_code 是 cancelled_by_request(PR #951)。不要把已取消 run 上的空 error_code 當成「未知」。
  • cancel_requested_at 有持久化,但不在 SandboxRunDetailResponse。看 status + error_code。
  • can_cancel_run == can_read_run。受限 key 仍只能看自己的 run。
  • 極少數情況下,若控制面在派工中途掛掉,run 可能卡在 starting。背景 reaper 會自動自癒(重新派送同一次 dispatch,剛好一次)——不需要租戶動作,這期間取消照樣可用。
Last updated on