// wait — 等待指定毫秒數後繼續(最多 30 秒) // // ⚠️ 已由引擎接手,這份 WASM 在 Cloudflare Workers 上跑不動(Arcrun#101,2026-08-12)。 // 現行實作在 cypher-executor/src/lib/constants.ts 的 BUILTIN_COMPONENTS['wait'], // component-loader step 1 先命中,這顆 wasm 不會再被工作流呼叫到。 // // 為什麼跑不動(不是「比較慢」,是「永遠不會結束」): // 下面的 time.Sleep 在 TinyGo 走 WASI poll_oneoff,而 component worker 的 WASI shim // 把 poll_oneoff 實作成 ENOSYS ⇒ TinyGo 排程器退化成迴圈重讀 clock_time_get 自旋; // Workers 的時鐘在無 I/O 的同步執行期間是凍結的 ⇒ 結束條件永遠不成立 ⇒ 一路燒到 // CPU 上限被砍(error 1102)。leo 實測 ms=3000/20000/30000 全在 ~35 秒後 503, // 死法與 ms 無關 —— 這正是「迴圈沒結束」而非「等待很貴」的證據。 // // 原本的舊註解寫「改用 busy-wait 模擬」是錯的:這個檔從來沒有 busy-wait, // 一直是 time.Sleep。那句話誤導了後來每一個讀這個檔的人。 // // 本次刻意不改行為、只改註解:手邊沒有 TinyGo 工具鏈,改了 main.go 卻沒重編, // 會讓 repo 內已 commit 的 .component-builds/wait/component.wasm 與原始碼漂移 // (rule 05「WASM 來源」:那份 wasm 是 self-host 用戶的部署來源)。 // 要退役這顆零件(刪目錄/下架 wait.arcrun.dev)是另一個決定,需人拍板。 package main import ( "encoding/json" "io" "os" "time" ) type Input struct { Ms int `json:"ms"` Context map[string]interface{} `json:"context"` } func main() { raw, err := io.ReadAll(os.Stdin) if err != nil { writeError("failed to read stdin: " + err.Error()) return } var input Input if err := json.Unmarshal(raw, &input); err != nil { writeError("invalid input JSON: " + err.Error()) return } if input.Ms <= 0 { writeError("ms 必須大於 0") return } ms := input.Ms if ms > 30000 { ms = 30000 } time.Sleep(time.Duration(ms) * time.Millisecond) result := make(map[string]interface{}) for k, v := range input.Context { result[k] = v } result["waited_ms"] = ms out, _ := json.Marshal(map[string]interface{}{"success": true, "data": result}) os.Stdout.Write(out) } func writeError(msg string) { out, _ := json.Marshal(map[string]interface{}{"success": false, "error": msg}) os.Stdout.Write(out) }