OxideTerm 節點工作階段所有權
每當更變可能影響哪個元件建立、共用、關閉、重新連線或觀察遠端工作階段或背景工作時,請使用此技能。
核心不變量
已連線的 SSH 節點獨立於任何使用它的終端面板。UI 生命週期不得悄悄變成後端生命週期。
flowchart TD
W["工作區或應用程式生命週期"] --> R["NodeRouter 與連線註冊表"]
R --> N["實體 SSH 節點連線"]
N --> T["終端消費者"]
N --> S["SFTP 消費者"]
N --> F["轉發消費者"]
R --> H["健康檢查與重新連線工作"]
強制規則
- 節點存活屬於連線註冊表、
NodeRouter或明確的節點斷線操作。 - 關閉終端面板會移除該終端消費者。它不得斷開一個共用節點。
- SFTP 必須取得一個真正的節點支援的 SFTP 工作階段。模仿檔案傳輸的 shell 指令只是一個有文件記載的相容性後備方案。
- 埠轉發擁有自己的監聽器與橋接任務。這些任務必須在沒有開啟終端面板的情況下保持存活,並且在轉發規則或所屬節點停止時必須停止。
- 重新連線、健康檢查、寬限期和子程序橋接需要一個明確的擁有者以及與節點、工作區或應用程式生命週期關聯的取消路徑。
- 長期工作不得在一次性執行時期上執行,該執行時期會在命令處理器返回時被丟棄。
- 透過跳板主機連線的子節點必須在子傳輸需要時保留父連線。
- UI 元件透過路由器或註冊表事件觀察執行時期狀態。它們不得從終端存在推斷節點存活。
- 在所有權轉移(建立、共用、失效、重新取得、取消以及在 UI 拆除後刻意存活)處添加簡潔的英文註解。
禁止的繞道
- 不得因為節點支援的 API 不方便就開啟第二個非受管的 SSH 傳輸。
- 不得透過選取與主機關聯的第一個終端面板來尋找連線。
- 不得將長期任務僅儲存在臨時對話方塊、命令處理器或終端檢視中。
- 不得僅僅因為一個通道、面板、SFTP 請求或轉發消費者關閉就將節點標記為已斷線。
- 不得讓產生的子程序或 Tokio 任務在沒有關閉訊號和有界限的完成路徑的情況下處於分離狀態。
建議實踐
- 在註冊表中將每個後端依賴項表達為消費者或擁有者,而不是依賴於隱含的
Arc保留。 - 將實體傳輸狀態保留在連線條目上,邏輯拓撲保留在
NodeRouter中。 - 讓斷線串聯遵循記錄的父-子連線身分,而不是比對主機字串。
- 將任務處理程式或取消發送器保留在生命週期定義工作的物件上。
- 偏好事件驅動的 UI 更新而非輪詢終端狀態。
相容性路徑
只有在明確、有界限且準確報告的情況下才允許相容性後備方案。它們不得被描述為原生的 SFTP、轉發或節點工作階段實作。即使對於臨時後備方案,也要記錄擁有者和清理路徑。
範例
錯誤:
// 關閉面板意外地銷毀了共用節點的唯一擁有者。
struct TerminalPane {
ssh_transport: SshTransport,
}
正確形式:
// 面板僅擁有自己的消費者註冊;註冊表擁有傳輸存活。
struct TerminalPane {
connection_id: String,
terminal_consumer: ConnectionConsumer,
}
錯誤:
tokio::runtime::Runtime::new()?.spawn(run_forward_listener());
// 執行時期在命令返回時被丟棄。
正確形式:
// 轉發擁有者保留取消和完成處理程式。
struct ForwardingJob {
shutdown_tx: Option<oneshot::Sender<()>>,
worker: JoinHandle<()>,
}
審查清單
- 識別實體連線擁有者。
- 列出每一個終端、SFTP、轉發、重新連線、健康檢查和子節點消費者。
- 驗證關閉一個消費者不會關閉不相關的消費者。
- 驗證明確的節點斷線會停止依賴的工作和子傳輸。
- 檢查每個產生的任務或程序是否有保留的擁有者、取消訊號和清理路徑。
- 檢查 UI 狀態是否消耗節點事件而非終端派生的存活狀態。
- 精確說明任何剩餘的相容性後備方案。
驗證
- 關閉最後一個終端並證明該節點仍可被另一個已註冊的消費者使用。
- 在不需終端面板的情況下開啟 SFTP。
- 啟動本地、遠端和動態轉發,並驗證監聽器在關閉面板後仍存活。
- 斷開父節點並驗證依賴的子節點和工作是否一致地轉換。
- 在寬限期內重新連線,而不遺失不相關的 UI 狀態。
- 確認任務/程序清理在明確斷線和應用程式關閉後完成。