Flow 作者指南

Flow 是任務的反應式場景監督器。它在中斷、節點動作失敗和未知畫面後重新觀察螢幕, 不恢復舊呼叫棧。

它不負責業務點選、路線規劃或跨任務頁面導航。節點 action 繼續使用任務原有的 wait_untilwait_click_confirm 和輸入 helper。

最小接入

BaseNTETask 已為每個 Task 單例建立 self.flow, 重新整理幀, 註冊月卡中斷, 並讓 Flow 執行期間的 wait_until() 自動成為安全點。任務只需要宣告自己的場景:

class Node(Enum):
    READY = "ready"
    RESULT = "result"
    TEAM = "team"

def _configure_flow(self):
    self.flow.node(Node.RESULT, self.has_result, self._on_result)
    self.flow.node(Node.READY, self.is_ready, self._on_ready)
    self.flow.node(Node.TEAM, self.is_in_team, self._enter_task)
    self.flow.fallback(self._press_escape_for_recovery, timeout=360)

在任務入口中執行它:

completed = self.flow.loop(
    lambda: self._session.is_finished,
    on_error=self._handle_flow_error,
    poll_interval=0.1,
)

節點 action 契約

  • detector 必須是無副作用的當前畫面判斷。優先順序只用於 detector 同時命中時的消歧, 預設按註冊順序。
  • action 可能在畫面持續可見時重複執行。它必須冪等, 或使用已有的 interval / wait_until 節流, 不能假定每次 action 都會立刻切換頁面。
  • action 的返回值不參與轉移判斷; Flow 只根據下一次畫面檢測決定下一步。
  • 可恢復的業務失敗丟擲既有異常, 通常是 WaitFailedException。Flow 重新整理畫面後先檢查原節點: 原節點仍在才交給 on_error; 原節點消失就直接重新分類。
  • 自定義高頻迴圈中呼叫 self.flow.safe_point()。它發現中斷會丟擲 FlowReplan; 如 action 需要記錄本輪狀態, 記錄後必須繼續丟擲它。
try:
    self._control_until_finished()
except FlowReplan:
    session.interrupted_control_round = session.round_index
    raise

不要在任務程式碼中呼叫 Flow 的內部中斷檢查。普通等待已經自動檢查; 自定義迴圈只使用 safe_point()

中斷與恢復語義

  • 中斷 handler 返回非 False 表示已處理。Flow 丟棄舊呼叫棧, 先觀察原節點。
  • 原節點在中斷後暫時未匹配時, Flow 最多等待 3 秒; 期間重新匹配則繼續原節點, 超時後才全量分類。
  • handler 返回 False 表示處理失敗。Flow 不會繼續舊 action, 而是立即執行 fallback, 不會重複執行該 handler 後才恢復。
  • 允許 handler 返回 False 的 Flow 必須註冊 fallback; 否則 loop() 會失敗而不是冒險繼續舊 action。
  • 未識別畫面會先容忍 5 秒; 之後反覆執行 fallback; 達到任務配置的 fallback timeout 才失敗。
  • TaskDisabledException 是控制流, 會直接離開 Flow, 不會被恢復邏輯吞掉。
在 GitHub 查看來源 ↗ · 頁面產生時間: 2026年8月9日