feat(due): 事件偵測與到期判定,七個事件名接上狀態來源

待辦簿存得住 trigger 與 recur,但沒有東西判「現在到期了沒有」。存放那一支的檔頭明寫它不判定、算的邏輯在別的地方,這一輪就是補那個別的地方。

另開一支而不併進存放那一支。那一支的檔頭把「我不判定」寫成合約,而合約是呼叫端唯一的依據;併進去就要推翻那整段話,而讀過舊版的人會以為那一支不判、自己再判一次,於是漂移從註解裡長出來。界線做成單向:判定這一支只讀待辦檔與印值,要改狀態一律回頭叫存放那一支的完成與失敗。

事件偵測靠比對狀態快照,不改任何產生者。每一輪讀那幾支產生者留下的狀態,跟上一輪存下的快照比,有差別就算事件發生。六個事件名各自接上本機狀態來源:工作包鎖檔轉態、階段檔換值、錯誤紀錄行數變多、工作階段開始與結束、日誌暫存區清空。

這個選擇有一個明確的代價,寫進檔頭:兩輪之間發生又消失的事件會漏掉。往後誰假設「事件不會漏」就會出錯,而那種錯是無聲的。不為了補這個洞去改那幾支產生者——要它們各自在事件發生那一刻多寫一筆,任何一支忘了寫就讓對應的事件從此不再發生,而那同樣無聲,還散在五個 domain 裡查不出是誰漏的。快照比對至少壞掉時看得出來。

第一次跑一律只建快照、不發事件,否則機器上所有既有狀態都會被當成剛發生,讓每一筆事件型待辦一次全到期。同一條理由逐個來源再套一次:某個來源上一輪不存在、這一輪才出現,那個來源這一輪也只建快照。所以快照要留一列記每個來源上一輪是看得到還是不存在——少了它就分不出「上一輪沒有這個來源」與「上一輪這個來源是空的」,而只有後者的差別才算事件。來源目錄從有變成不見時也不發事件,只記警示:整個目錄被砍掉不是每一支工作包都合併了。

四種組合一個都不壓。時鐘型的排定點從那個時間往後數、一次加一個間隔,不從上次執行起算——每次拿上次執行加間隔,執行慢幾秒就往後挪幾秒,一天下來就偏掉。漏掉的排定點只補一次不逐個追補,否則機器關一天再開會連續跑幾十輪同一件事。事件型配間隔時,那個間隔照存放那一支的定義當「重新武裝的最短間隔」。

事件型的下次執行時間一律留空。事件型沒有預定時間,唯一算得出來的是重新武裝時刻,但那個值填進去會被狀態表與提醒讀成「那個時間會跑」,它其實只是「那個時間之前不會跑」,差別在畫面上看不出來。那個值改印成另一個欄位,要看的人看得到。

規格有兩條在同一個欄位上打架。同一件事不重複觸發的判準是「事件發生時間比上次執行晚」,但失敗也會寫上次執行,於是失敗過的事件型待辦再也等不到同一次事件,也就永遠不重試——而規格明確要求失敗照重試。改用連續失敗次數當第三個判準把兩者分開:狀態還是待辦而次數大於零,代表上一次執行失敗,一律算到期,不再比事件也不看排定點。完成會把次數歸零,所以成功那一次不會被誤判成要重試。

兩項刻意標成未接線並吵出來,不假裝算得出來。分析完成那一個事件的狀態來源在 wiki 上、要連網要金鑰,混進來之後金鑰一過期就讓事件偵測整項每輪失敗;更糟的是判不出來時那幾筆會靜靜地永遠不到期,跟填一個不存在的事件名一樣看不出壞在哪。cron 式子同理,五個欄位的萬用字元與步進算錯一格就是差一小時或差一天,而那種錯要等真的跑錯才看得出來。兩者的處置都是印一行未接線、列進要人接手那一節,明說「這一筆現在判不出到期,不是還沒發生」。

間隔格式規格從來沒定義過,這一輪定成正整數加單位,刻意不收裸數字——排程週期以分鐘算、心跳門檻以秒算,裸數字兩種都讀得通,讀錯就差六十倍。

巡檢那一路一併接上:快照要有人推進才活得起來。刻意不把它算進既有五項的成敗,避免動到摘要表的欄名與本輪項目那一列的文字,舊頁那些列的欄名不會跟著改,同一張表就會有兩種寫法。失敗時改成記警示與待人處理。

順手修掉一個同類的坑:用冒號當空指令去清空檔案時,重導向失敗會讓整個殼直接結束,後面的分流一次都跑不到。這一支一律改用 true 並把理由寫進註解。
This commit is contained in:
2026-09-03 16:37:44 +08:00
parent e7edfcbec0
commit 737fcf13fd
3 changed files with 1254 additions and 8 deletions
Executable
+1161
View File
File diff suppressed because it is too large Load Diff