Files
Arcrun/MIGRATION.md
T
Claude 39e6f59178 feat(workflow-store): workflow 真相源 KV → KBDB API(entry_type=workflow)
SDD kbdb-base §8.3/§8.4 P2+P3。總管裁定 2026-07-06:
① upsert 走 KBDB base PUT /entries(by owner_id+page_name+entry_type)
② cron 掃 KBDB、不保留 KV cron-idx
③ 一 workflow=一筆 entry_type=workflow;content=description(保 embed)、
   graph+config+cron_expr 進 metadata_json

KBDB:
- entry-crud.ts 加 upsertEntry(read-then-write,無 UNIQUE、表不變)
- entries.ts 加 PUT /entries(upsert,回 created 旗標,content 變動時 embed-on-write)

cypher-executor:
- 新增 lib/workflow-store.ts(走 kbdbBase,禁直連 D1)
- webhooks-named register/trigger/list/delete 切雙軌(讀先 KBDB miss fallback KV、
  寫 KBDB 為主+暫雙寫 KV);writeWorkflowSearchEntry 上收進 putWorkflow(修重複 entry bug);
  backfill 升級為 KV→KBDB 遷移入口;移除 migrate-cron-index 端點
- scheduled 改掃 KBDB(listCronWorkflows);刪除 lib/cron-index.ts
- component-loader(trigger_workflow)、executions 擁有權檢查切雙軌讀

tsc 0 error;kbdb vitest 6/6;cypher vitest 41/42(1 失敗為 pre-existing,與本 PR 無關)。
不 merge、不部署、不動 production KV workflow。搬遷步驟見 MIGRATION.md。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJiLCRUU2o3aSpPEzVCt2o
2026-07-06 13:55:16 +00:00

6.7 KiB
Raw Blame History

MIGRATION — workflow 真相源 WEBHOOKS KV → KBDB APIentry_type=workflow

分支:feat/workflow-store-kbdb SDDsystem-dev/docs/3-specs/arcrun/kbdb-base/design.md §8.3/§8.4 總管裁定(2026-07-06):① upsert 走 KBDB base PUT /entries;② cron 掃 KBDB、不保留 KV cron-idx ③ 一 workflow = 一筆 entry_type=workflowcontent=description(保 embed),graph+config+cron_expr 進 metadata_json

本 PR 不 merge、不部署、不動 production 那 7 筆 KV workflow。 data 搬遷是下一階段(leo 寫入閘)。


1. 這個 PR 改了什麼

KBDB(新增能力)

  • kbdb/src/actions/entry-crud.ts:新增 upsertEntry(db, input) — by (owner_id, page_name, entry_type) read-then-write(無 UNIQUE 約束、表不變鐵律;命中最舊一筆更新,重跑收斂)。
  • kbdb/src/routes/entries.ts:新增 PUT /entriesupsert,回 { success, entry, created }content 變動時 embed-on-write)。

cypher-executorworkflow store + 六路 + 兩路切雙軌)

  • 新檔 cypher-executor/src/lib/workflow-store.tsgetWorkflow / listWorkflows / putWorkflow / deleteWorkflow / listCronWorkflows,全走 KBDB base APIkbdbBase = KBDB_BASE_URL + 選用 KBDB_INTERNAL_TOKEN),owner_id=namespace 租戶隔離。禁直連 D1/SQL。
  • routes/webhooks-named.ts
    • register:寫 putWorkflow(KBDB 為主)+ 暫雙寫 KV;移除 writeWorkflowSearchEntry(上收進 putWorkflow 修掉每次 POST 堆重複 entry 的 bug);移除 KV cron-idx 維護。
    • trigger / list / delete:讀先 KBDB、miss fallback KVlist = KBDB KV(同名 KBDB 為準);delete 兩邊都刪。
    • backfill-search-entries:升級為 KV→KBDB 完整遷移入口putWorkflow upsert,冪等可重跑)。
    • 移除 migrate-cron-index 端點(KV cron-idx 已退場)。
  • scheduled.tscron 掃描改 listCronWorkflows(掃 KBDB、記憶體濾 cron_expr);不再讀 KV cron-idx。
  • lib/component-loader.tstrigger_workflow 子流程)、routes/executions.ts(擁有權檢查):切雙軌讀。
  • 刪除 lib/cron-index.tsKV cron-idx 模型退場)。

綠燈

  • kbdb tsc 0 error、vitest 6/6 綠。
  • cypher-executor tsc 0 error、vitest 41/42 綠(1 個 executor.test.ts > 不存在的零件 失敗為 pre-existing,main 上同樣失敗,與本 PR 無關——component-not-found 錯誤訊息措辭斷言,非 workflow 路徑)。

2. 部署後驗證計畫(對真端點 curl,禁 miniflare 假綠)

前提:部署到 leo21c(auto 模式本輪不做;下述為部署後的驗收步驟)。 端點:cypher https://arcrun-cypher-executor.leo21c.workers.dev、KBDB https://arcrun-kbdb.leo21c.workers.dev全程只用測試 namespace(如 ak_wfmigtest),不碰現有 7 筆 production workflow。

NS=ak_wfmigtestCY=https://arcrun-cypher-executor.leo21c.workers.devKB=https://arcrun-kbdb.leo21c.workers.dev

  1. KBDB upsert 端點本身
    curl -XPUT $KB/entries -H 'content-type: application/json' \
      -d '{"entry_type":"workflow","owner_id":"'$NS'","page_name":"t1","content":"desc A","metadata_json":"{\"graph\":{\"id\":\"g\"}}"}'
    # → { success:true, created:true }
    # 再打一次(改 content:"desc B")→ { success:true, created:false }(同一 entry 更新,非新增)
    curl "$KB/entries?entry_type=workflow&owner_id=$NS&page_name=t1"   # → 恰 1 筆、content="desc B"
    
  2. register(部署)→ 恰一筆、redeploy 不重複
    curl -XPOST $CY/webhooks/named -H "X-Arcrun-API-Key: $NS" -H 'content-type: application/json' \
      -d '{"name":"wf_a","description":"測試工作流","graph":{"id":"wf_a","nodes":[]}}'
    curl "$KB/entries?entry_type=workflow&owner_id=$NS&page_name=wf_a"   # → 恰 1 筆
    # 同名再 POST 一次(改 description)→ 仍恰 1 筆、content 更新(驗 upsert 冪等,無重複 entry bug
    
  3. list / trigger / delete 走 KBDB
    curl $CY/webhooks/named -H "X-Arcrun-API-Key: $NS"                  # → 含 wf_a,欄位齊
    curl -XPOST $CY/webhooks/named/wf_a/trigger -H "X-Arcrun-API-Key: $NS" -d '{}'   # → 執行(讀到 KBDB graph
    curl -XDELETE $CY/webhooks/named/wf_a -H "X-Arcrun-API-Key: $NS"    # → {deleted:true}
    curl "$KB/entries?entry_type=workflow&owner_id=$NS&page_name=wf_a"  # → 0 筆
    
  4. cron 掃 KBDB:部署一個首節點為 cron 的 workflowcron_expr 每分鐘),等 12 分鐘看 wrangler tail [scheduled] scanned N KBDB cron workflows, k triggered 有觸發。
  5. 雙軌 fallback(不寫 KBDB 的舊 KV workflow 仍可 trigger:手動塞一筆 {NS}:wf:legacy 進 WEBHOOKS KV (只 KV、不進 KBDB),打 /webhooks/named/legacy/trigger → 應 fallback KV 成功執行;GET /webhooks/named 應同時列出 KBDB 的與這筆 KV-only 的(union)。

驗收標準:上述每步 HTTP status + 回傳體符合預期;特別是「redeploy 同名恆為 1 筆」(upsert 生效) 與「cron 從 KBDB 觸發」。缺任一即不算綠,回報而非假綠(mindset §7)。


3. 剩餘 data 搬遷步驟(下一階段,leo 寫入閘,本輪別做)

現有 7 筆 production workflow 仍只在 WEBHOOKS KV。雙軌讀讓它們仍可 trigger,但:

  • cron 掃描只看 KBDB → 若這 7 筆裡有 cron workflow,未搬遷前它們的排程會停止觸發⚠️ 高優先)。
  • semantic 搜尋也只看 KBDB entry。

搬遷程序(冪等、可重跑)

  1. 逐 namespace 呼叫 POST /workflows/backfill-search-entries(帶該租戶 X-Arcrun-API-Key)。 它 list KV 的 {ns}:wf:*、對每筆 putWorkflowupsert)遷進 KBDB。回傳 backfilled / needs_description
  2. 驗證:GET $KB/entries?entry_type=workflow&owner_id={ns} 每筆都有對應 entrygraph 在 metadata)。
  3. needs_description 清單交操盤 CC re-deploy 時據實補描述(不自動編造)。
  4. 全部驗穩後,才由 leo 決定拆掉 register 的 KV 雙寫 + trigger/list/delete 的 KV fallback(另一次閘)。 拆除前 KV 是安全網,不要急著拿掉。

誰有幾筆、哪些是 cron,需先盤點(WEBHOOKS.list 或 console)再排搬遷順序(cron 的先搬)。


4. 回滾

本 PR 不動 production 資料,且 register 仍雙寫 KV、讀有 KV fallback → 直接 revert 分支即可回到「KV 為真相源」。 KBDB 端只新增 PUT /entries(不改既有端點行為),revert cypher 側即停用;KBDB 側可留(無副作用)。 唯一不可逆的取捨:本 PR 刪了 cron-index.tsmigrate-cron-index 端點(KV cron-idx 退場); 如需回滾 cron 到 KV,從 git 歷史取回即可。