feat(km-wiki-ingest): 重做成跑在 cypher 上的 workflow(走 cypher binding,汰換 service-binding drainer,D28)
把知識庫 ingest 從 standalone drainer(誤用 Service Bindings)重表達為 cypher workflow:
- workflow.yaml(Phase 0 cron drain):watch_cron→load_cursor→list_cards→pick_card(code)
→fetch_card→parse_card(code)→upsert_entry→save_cursor→post_envelopes→post_one_envelope。
線性 pipe,跨-worker 全走 cypher binding(零件節點),零 service binding。
- workflow.delta.yaml(Gitea webhook 穩態):collect_changed(code)→foreach card→fetch/parse/upsert/foreach envelope。
- code/kbdb/graph 接法:code=canonical `code` 零件(arcrun-code);kbdb/graph=http_request 零件打
/entries/ingest、/triplets/ingest(server 端冪等);Gitea=http_request。
- 平台端最小補丁(各需 gated 部署):
1) cypher-executor component-loader:WASM_HTTP_RUNNER_IDS 加 'code'(canonical→arcrun-code,cypher binding 正解)。
2) kbdb base:POST /entries/ingest(page_name+content_hash 冪等 upsert,對稱 graph /triplets/ingest;
因 flow DSL 無資料條件分支,把 create/patch/skip 冪等推到 server 端)。
- drainer/DEPRECATED.md:標舊 standalone worker 退役計畫(新版穩定後 wrangler delete)。
- DEPLOY.md:部署順序、cron/webhook 掛法、subdomain 對齊、驗收與退役。
本輪不部署(待總管/leo 審架構)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJiLCRUU2o3aSpPEzVCt2o
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# km-wiki-ingest — 部署(cypher workflow 版,走 cypher binding)
|
||||
|
||||
> **架構(D28)**:知識庫 ingest =**跑在 cypher-executor 上的 workflow**,跨-worker 呼叫全走
|
||||
> **cypher binding**(零件節點,由 component-loader 解析),**零 Service Bindings**。
|
||||
> 汰換舊的 standalone `arcrun-km-wiki-drainer`(`drainer/`,已誤用 service binding → 見 `drainer/DEPRECATED.md`)。
|
||||
>
|
||||
> **本輪不部署**(等總管/leo 審架構)。以下是過閘後的部署順序。
|
||||
|
||||
## 0) 先決條件(兩個平台端小改,皆本分支已含,需各自 gated 部署)
|
||||
|
||||
這兩處是「讓 workflow 能純走 cypher binding」的最小平台補丁,**不是** ingest 專屬邏輯:
|
||||
|
||||
1. **cypher-executor:`code` 零件進 loader 白名單**
|
||||
- 檔:`cypher-executor/src/lib/component-loader.ts` → `WASM_HTTP_RUNNER_IDS` 加 `'code'`(本分支已加 1 行)。
|
||||
- 效果:workflow 節點 `component: code` → 解析成 `arcrun-code.{WORKER_SUBDOMAIN}.workers.dev`(cypher binding)。
|
||||
- 部署:`cd cypher-executor && npx wrangler deploy`(要 leo 過閘;動到共用 executor)。
|
||||
- **替代(不改 executor)**:把兩個 workflow 裡 `component: code` 改成 code 的完整 URL
|
||||
`component: "https://arcrun-code.<subdomain>.workers.dev"`(走 loader step 2 外部 URL)。省一次 executor 部署,
|
||||
但少了「canonical 零件」的乾淨語義。建議用白名單版(這才是 D28 說的 cypher binding)。
|
||||
|
||||
2. **KBDB base:`POST /entries/ingest`(server 端冪等 upsert)**
|
||||
- 檔:`kbdb/src/routes/entries.ts`(本分支已加)。語義對稱 graph 的 `/triplets/ingest`:
|
||||
page_name 當鍵、`content_hash` 同 → skip、不同/無 → update、無則 create。
|
||||
- 為何需要它:cypher 的 flow DSL **無資料條件分支**(只有 ON_SUCCESS/ON_FAIL/FOREACH),
|
||||
無法在 workflow 內做「查→比對→create 或 patch」三岔。把冪等推到 server 端,workflow 只打一發。
|
||||
- 部署:`cd kbdb && npx wrangler deploy`(要過閘)。
|
||||
|
||||
> ⚠️ **subdomain 對齊**:兩個 workflow 內的 URL 用 `uncle6-me`(官方 `WORKER_SUBDOMAIN`,見 `cypher-executor/wrangler.toml`)。
|
||||
> 若你的 arcrun-kbdb / kbdb-graph-plugin / arcrun-code 部在別的 workers.dev subdomain(例 `leo21c`),
|
||||
> 把兩檔的 URL 一起改。**舊 standalone drainer 誤用 `leo21c` 是坑之一。**
|
||||
|
||||
## 1) CLI 設定
|
||||
|
||||
```bash
|
||||
# self-hosted(namespace 明碼分區):
|
||||
acr config set mode self-hosted
|
||||
acr config set cypher_url https://cypher.arcrun.dev # 或你自架的 executor
|
||||
echo "NAMESPACE=leo" >> .env
|
||||
# standard(平台多租戶):acr init 取 api_key
|
||||
```
|
||||
|
||||
## 2) 設 Gitea token(機密;節點以 {{credential.gitea_token}} 引用)
|
||||
|
||||
```bash
|
||||
acr creds set gitea_token <你的 GITEA_TOKEN> # 讀 Leo/notes 用
|
||||
```
|
||||
> graph 的 `X-Arcrun-API-Key: leo` 是 namespace 字串(非機密),已內嵌節點,不需設 credential。
|
||||
|
||||
## 3) 部署 Phase 0 drain(cron 觸發)
|
||||
|
||||
```bash
|
||||
acr push workflow.yaml
|
||||
```
|
||||
- `watch_cron` 的 `cron_expr: "*/2 * * * *"` 會被 `webhooks-named` 的 `extractCronExpr` 抓出,
|
||||
寫進 `cron-idx:_all`;cypher `scheduled()` 每分鐘比對觸發本 workflow(**不需另設 CF cron**)。
|
||||
- 游標**不需 seed**:首跑 `load_cursor` GET 回空 → `pick_card` 從頭;`save_cursor` 首 tick 自動 create。
|
||||
- 手動補跑一 tick(驗收):`acr run km_wiki_ingest_drain`
|
||||
|
||||
## 4) 部署穩態 delta(Gitea webhook 觸發)
|
||||
|
||||
```bash
|
||||
acr push workflow.delta.yaml
|
||||
```
|
||||
- 取得 trigger URL(self-hosted 例):
|
||||
`https://cypher.arcrun.dev/webhooks/named/leo/km_wiki_ingest_delta/trigger`
|
||||
- Gitea repo `Leo/notes` → **Settings → Webhooks → Add Webhook → Gitea**:
|
||||
- Target URL:上面的 trigger URL
|
||||
- Content-Type:`application/json`
|
||||
- Trigger:Push events
|
||||
- (standard 模式改帶 `X-Arcrun-API-Key` header;self-hosted 免 header,namespace 在 path)
|
||||
- 這是 Gitea→Cloudflare(cypher),**非 GitHub Actions** → 不觸 GitHub flag(D4/D20)。
|
||||
|
||||
## 5) 驗收
|
||||
|
||||
```bash
|
||||
# entry 落地?
|
||||
curl -s "https://arcrun-kbdb.uncle6-me.workers.dev/entries?owner_id=leo&entry_type=wiki_card&limit=5" | jq '.count'
|
||||
# triplet 落地?
|
||||
curl -s "https://kbdb-graph-plugin.uncle6-me.workers.dev/graph?owner_id=leo" | jq '.nodes|length'
|
||||
# 游標?
|
||||
curl -s "https://arcrun-kbdb.uncle6-me.workers.dev/entries?owner_id=leo&page_name=cursor:km_wiki_ingest_drain:Leo/notes" | jq '.entries[0].content'
|
||||
```
|
||||
冪等自證:連跑兩次 `acr run km_wiki_ingest_drain`,第二次同卡 entry `action:skipped`、graph per-source no-op。
|
||||
|
||||
## 6) 舊 standalone drainer 退役
|
||||
|
||||
- 全 drain 完 + delta webhook 穩定收斂後,退役 `arcrun-km-wiki-drainer`:`wrangler delete arcrun-km-wiki-drainer`。
|
||||
- 保留 `drainer/` 原始碼一個週期(含 `DEPRECATED.md`)供對照,確認新版逐卡輸出與舊版一致再刪。
|
||||
- 見 `drainer/DEPRECATED.md`。
|
||||
|
||||
## 節點圖速覽
|
||||
|
||||
**drain(cron)**:`watch_cron(cron)` → `load_cursor(http GET kbdb)` → `list_cards(http GET Gitea tree)`
|
||||
→ `pick_card(code)` → `fetch_card(http GET Gitea raw)` → `parse_card(code)`
|
||||
→ `upsert_entry(http POST kbdb /entries/ingest)` → `save_cursor(http POST kbdb /entries/ingest)`
|
||||
→ `post_envelopes(foreach)` → `post_one_envelope(http POST graph /triplets/ingest)`
|
||||
|
||||
**delta(webhook)**:`collect_changed(code)` →〔對每個 card〕→ `fetch_card_d` → `parse_card_d(code)`
|
||||
→ `upsert_entry_d(http)` → `post_envelopes_d(foreach)` → `post_one_envelope_d(http)`
|
||||
|
||||
零件對應的 cypher binding:`code`→arcrun-code;`http_request`→arcrun-http-request(打 Gitea/kbdb/graph);
|
||||
`cron`→觸發登記;`foreach_control`→平台 logic primitive(唯一允許的 service-binding 用法:零件等級,非本工作流編排)。
|
||||
**全程無工作流等級的 service binding。**
|
||||
Reference in New Issue
Block a user