在做 APR 的時候有時候會發生:Place 已經過了,主管忽然說要多檢查加檢查、或是把後面某條旁路先拿掉,這類可能會動到 DAG 的需求
但 WinFlow 的大原則
執行中的 DAG 不能一邊跑、一邊被換成另一張圖。
解法有一條路:先讓 Runner 閒下來,到 Generator 改,再按 Sync from Generator 把新 DAG 灌回去。今天就介紹這個功能。
Runner 排程靠的是當下這份 parents / children:誰 DONE,誰的 remaining 減一,減到零就 bsub。若 Place 還在 RUN,你卻在另一個分頁把 Q_PLACE 接到 CTS 前面,會出現三種一起壞掉的事:
所以 Sync 被設計成:只在 Runner 閒置時,整份換圖,狀態歸零。 互動的意思是「改完再換手」,不是「邊跑邊縫」
兩個分頁能換手,是因為同一個視窗把 Generator 當成 Runner 的 sync_source:
WinFlowApp
├── Generator (記憶體裡的 FlowDocument)
└── Runner (sync_source = Generator)
└── 頂列按鈕 Sync from Generator
互動式改圖,預設走 python winflow_gui.py 那個統一視窗。
按鈕亮起的條件只有兩個,且兩個都要成立:
| 條件 | 不成立時 |
|---|---|
is_running 為假 |
整條 flow 還在跑 |
| 沒有正在 kill 的對象 | Stop 後的 bkill 還沒確認完 |
跑到一半要改 DAG
→ Stop(等到紫的 KILLING 結束、按鈕恢復可按)
→ 切 Generator 改
→ 切 Runner 按 Sync
→ 按 Validate ALL 把跑完的 job status 設回來
1. 再確認一次:沒在跑、沒在 kill
2. 若 registry 裡還有「看起來活著」的 LSF job
→ 跳出 Yes/No:Sync 還是會換圖,cluster 上的作業不會被這顆按鈕殺掉
3. 向 Generator 要記憶體裡的 flow
get_flow_dict()
→ 套用畫面上的 flow name / poll interval
→ document_to_flow()
重複 stage 名自動改成 name_2
依畫布座標重排 JSON 順序
seed_relations=False(保留你 Unlink 掉的邊)
4. 寫進 Generator 指定的路徑(預設 flow.json)
5. 立刻從磁碟再讀回來
6. Runner 的 Config 指到這份檔
7. 用新 JSON 重建 DAG,所有節點 reset 成 waiting
8. 狀態列寫 Synced,log 記 job 數與 stage 名
第 5 步看起來囉嗦:寫完為什麼還要讀?因為接下來按 Run,吃的是檔案裡的那份,不是記憶體裡「以為寫出去」的那份。寫入成功但讀回來失敗,會報錯停住,避免畫布一套、真正執行另一套。
第 7 步是互動式方案裡最容易被低估的:Sync 不會記得剛才哪些是綠的。job key 可能因加節點、改 stage 名、重排而變掉,硬留舊狀態比全部重來更危險。所以畫布會先全部變回灰 (但你還是可以透過 validate all 把狀態設回來)。
跟 Export flow.json 的差別也在這裡。Export 只負責把 Generator 寫到磁碟,Runner 不會自動換圖。Sync 是 Export 再加「灌進 Runner + 狀態歸零」。改完若只 Export、忘了 Sync,你盯著的還是舊 DAG
flow.json 被覆寫,DAG 換成新圖,顏色全灰。這篇就當作 WinFlow 2.0 的總結吧
其實整個專案就做四件事:
flow.json 是契約,根據各家公司可以有所不同,讓流程不寫死在程式裡parents / children,提交前驗 inputs、DONE 後驗 outputs這個專案未來應該還是會持續更新,像我覺得用範本 build 那一塊就弄得還不是那麼方便,應該要做到讓使用者只需要提交一個 config like 的設定檔,就要高枕無憂了,另外很多細節的文件也還沒補齊。這 13 篇文章過來,大概有一半是 AI 幫我寫得 XD,我就看看修改細節跟上圖片而已,我寫到第 7 天的時後發現自己的文字表達能力,可能不是很理想,想說試看看讓 AI 來寫,然後發現是真的是滿厲害的,雖然有時候他的語法很 ... 不像人的口語,但技術上的說辭還是相當正確的,所以後來我有回頭從 DAY 03 再翻新一遍,看完一次後我覺得是比之前寫的好多了 😄
接下來下個主題我覺得就比較平凡一點,就只是打造一個小網頁而已,那就讓我們下篇再見吧 ~