feat(ingest-hash-trigger): collector R2 content-addressed 原稿上傳(SDD task 3)
- collector upload 子命令=scan+把 added/modified 原稿傳 R2(CF REST API Bearer token,key=raw/<sha256hex>,對齊 collector-trigger.v1 的 r2_key) - 冪等:存在檢查命中=skipped_exists 不 PUT;CF API objects 端點不支援 HEAD(live 實測 405)→ 改 GET+Range: bytes=0-0 - 完整性:上傳前重算 hash 核對 key,不符=failed 不上傳 - 失敗語意:failed → exit 1,ingested_hash 不動=下輪自動重試; 回寫鉤子 Manifest.MarkIngested 留給 task 4 - 設定只走環境變數 CF_ACCOUNT_ID/CF_API_TOKEN/R2_BUCKET,不落 repo - go test 14/14 綠(httptest mock 對齊真 API:HEAD 405);live e2e 全通 (arcrun-rag-raw-demo:真上傳→重傳 no-op→下載 diff 一致+sha256==key) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+15
@@ -75,6 +75,21 @@ func LoadManifest(path, root string) (*Manifest, error) {
|
||||
return &m, nil
|
||||
}
|
||||
|
||||
// MarkIngested 是「整條 ingest 鏈成功」後的回寫鉤子(design §2):把該路徑的
|
||||
// ingested_hash 接上當時送出的 source_hash。**R2 上傳成功不呼叫它**——上傳只是鏈的
|
||||
// 第一環,要等 task 4(named-webhook → ingest workflow)確認成功才回寫;在那之前
|
||||
// 同檔每輪重發 added/modified=設計內重試,R2 端靠 HEAD no-op 天然冪等、零浪費。
|
||||
// 回傳 false=路徑已不在 manifest(例如回報前檔案又被改名/刪除),呼叫端自行決定忽略或告警。
|
||||
func (m *Manifest) MarkIngested(path, sourceHash string, at int64) bool {
|
||||
e, ok := m.Entries[path]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
e.IngestedHash = sourceHash
|
||||
e.IngestedAt = at
|
||||
return true
|
||||
}
|
||||
|
||||
// Save 原子寫入(temp + rename),避免掃描中斷留半個 JSON。
|
||||
func (m *Manifest) Save(path string) error {
|
||||
data, err := json.MarshalIndent(m, "", " ")
|
||||
|
||||
Reference in New Issue
Block a user