釋出:到期清單的路徑一律由呼叫端餵進來,並拒跑過舊的清單 #37

Merged
admin merged 3 commits from develop into master 2026-09-07 01:25:47 +00:00
2 changed files with 40 additions and 1 deletions
Showing only changes of commit ccb28e2bb3 - Show all commits
+7
View File
@@ -205,6 +205,7 @@ WARN=0
DUE_STATUS=fail DUE_STATUS=fail
DUE_RC=0 DUE_RC=0
DUE_MD='' DUE_MD=''
DUE_ROWS=''
DUE_NOTE='' DUE_NOTE=''
DUE_TASKS='' DUE_TASKS=''
DUE_EVENTS='' DUE_EVENTS=''
@@ -912,6 +913,11 @@ due_scan() {
JSC_HOME="$JSC_HOME" sh "$_due" scan --out "$RD/due" >"$RD/due.out" 2>"$RD/due.err" </dev/null || _rc=$? JSC_HOME="$JSC_HOME" sh "$_due" scan --out "$RD/due" >"$RD/due.out" 2>"$RD/due.err" </dev/null || _rc=$?
DUE_RC="$_rc" DUE_RC="$_rc"
DUE_MD=$(sed -n 's/^due_file=//p' "$RD/due.out" 2>/dev/null | head -n1) DUE_MD=$(sed -n 's/^due_file=//p' "$RD/due.out" 2>/dev/null | head -n1)
# 機器可讀的那一份也要轉出去。判到期與執行是兩支腳本,中間靠這個檔案交棒;不轉出去
# 呼叫端就只能靠預設路徑猜,而那個預設指向的是上一次有人手動跑 scan 留下的檔案。
# 實測踩過:那份舊清單在機器上放了六小時,執行那一支每一輪都對它動手,跑的是一筆已經
# 被移除的待辦,而且看起來完全正常——舊清單當時是對的,內容剛好沒變。
DUE_ROWS=$(sed -n 's/^rows_file=//p' "$RD/due.out" 2>/dev/null | head -n1)
DUE_TASKS=$(sed -n 's/^tasks_due=//p' "$RD/due.out" 2>/dev/null | head -n1) DUE_TASKS=$(sed -n 's/^tasks_due=//p' "$RD/due.out" 2>/dev/null | head -n1)
DUE_EVENTS=$(sed -n 's/^events_new=//p' "$RD/due.out" 2>/dev/null | head -n1) DUE_EVENTS=$(sed -n 's/^events_new=//p' "$RD/due.out" 2>/dev/null | head -n1)
case "$_rc" in case "$_rc" in
@@ -1157,6 +1163,7 @@ case "$CMD" in
printf 'due_status=%s\n' "$DUE_STATUS" printf 'due_status=%s\n' "$DUE_STATUS"
printf 'due_rc=%s\n' "$DUE_RC" printf 'due_rc=%s\n' "$DUE_RC"
printf 'due_file=%s\n' "$DUE_MD" printf 'due_file=%s\n' "$DUE_MD"
printf 'due_rows_file=%s\n' "${DUE_ROWS:-}"
printf 'pending=%s\n' "$PEND_COUNT" printf 'pending=%s\n' "$PEND_COUNT"
printf 'events_total=%s\n' "$EV_TOTAL" printf 'events_total=%s\n' "$EV_TOTAL"
printf 'events_bad=%s\n' "$EV_BAD" printf 'events_bad=%s\n' "$EV_BAD"
+33 -1
View File
@@ -95,7 +95,19 @@ case "$JSC_HOME_RESOLVED" in
/*) ;; /*) ;;
*) die 6 'JSC_HOME 與 HOME 都解不出絕對路徑,找不到助理狀態目錄。' ;; *) die 6 'JSC_HOME 與 HOME 都解不出絕對路徑,找不到助理狀態目錄。' ;;
esac esac
[ -n "$ROWS" ] || ROWS="$JSC_HOME_RESOLVED/assistant/due/rows.txt" # --rows 沒有預設值,一律要指定。
#
# 原本有預設,指向助理狀態目錄底下那一份。那個預設是這一支上線之後最嚴重的一個缺陷:
# 判到期那一支是被巡檢用 --out 叫的,輸出寫進那一輪自己的暫存目錄,跟這個預設不是同一個
# 位置。於是這一支每一輪讀的都是「上一次有人手動跑 scan 留下的那一份」。實測那份清單在
# 機器上放了六小時,這一支每一輪都對它動手,還跑了一筆已經被移除的待辦。
# 而它看起來完全正常——那份舊清單產生的當下是對的,內容剛好沒變。**錯了六小時才顯形。**
#
# 所以不留預設。少帶這個選項就回用法錯誤,吵一次總比安靜地對舊資料動手好。呼叫端要拿
# collect 印的 due_rows_file= 餵進來,那是同一輪產生的那一份。
if [ -z "$ROWS" ]; then
die 6 '沒有帶 --rows。這一支不猜到期清單的位置:判到期那一支的輸出寫在叫它的人指定的目錄裡,猜一個預設就會讀到別人留下的舊檔案,而舊檔案讀起來跟新的一模一樣。請把 collect 印的 due_rows_file= 餵進來。'
fi
[ -f "$ROWS" ] || die 2 "到期清單讀不到:$ROWS。請先跑 due.sh scan——沒跑過判定,跟「都沒到期」不是同一件事。" [ -f "$ROWS" ] || die 2 "到期清單讀不到:$ROWS。請先跑 due.sh scan——沒跑過判定,跟「都沒到期」不是同一件事。"
@@ -121,6 +133,26 @@ find_tool() { # $1=domain $2=相對路徑
return 1 return 1
} }
# 清單太舊就拒跑。判到期與執行之間隔著呼叫端,那一段有可能斷掉——collect 失敗了而那一輪
# 照樣往下走,或呼叫端餵進上一輪的路徑。兩種都會讓這一支對著一份不描述現況的清單動手,
# 而那正是它上線之後六小時裡在做的事。
# 門檻取心跳的過期門檻:那是這台機器認定「一輪跑完的紀錄還算新鮮」的長度,一份比它還舊的
# 到期清單本來就不可能是這一輪產生的。讀不到門檻就退回 300 秒,跟心跳那一支的預設一致。
_ttl=''
if _hb=$(find_tool hooks hooks/heartbeat.sh 2>/dev/null); then
_ttl=$("$_hb" report 2>/dev/null | sed -n 's/.*[[:space:]]ttl=\([0-9]*\).*/\1/p' | head -n1)
fi
case "${_ttl:-}" in
''|*[!0-9]*) _ttl=300 ;;
esac
_mtime=$(date -r "$ROWS" +%s 2>/dev/null) || _mtime=''
if [ -n "$_mtime" ]; then
_age=$((NOW - _mtime))
if [ "$_age" -gt "$_ttl" ]; then
die 2 "到期清單是 $_age 秒前產生的,超過門檻 $_ttl 秒,這一支不對它動手:$ROWS。一份比心跳門檻還舊的清單不可能描述這一輪,照著跑會動到已經不存在的待辦。請確認判到期那一步這一輪真的跑成功了,再把它印的路徑餵進來。"
fi
fi
TASKS_SH="$HERE/tasks.sh" TASKS_SH="$HERE/tasks.sh"
[ -f "$TASKS_SH" ] || TASKS_SH=$(find_tool assist tools/tasks.sh) \ [ -f "$TASKS_SH" ] || TASKS_SH=$(find_tool assist tools/tasks.sh) \
|| die 2 '找不到 tasks.sh,成敗沒有地方回寫。待辦簿只有一個寫入者,缺了它這一輪不該跑。' || die 2 '找不到 tasks.sh,成敗沒有地方回寫。待辦簿只有一個寫入者,缺了它這一輪不該跑。'