89d9b314fb
釘子:c1566cf → 8be98b8(release 1.4.20,source Arcrun@c7a0b31) jsDelivr 已驗(用戶端的路,四個檔全 200 且內容逐項對): manifest release=1.4.20 core=5 顆(懶載設計保住) cypher ANALYTICS_KV.put 殘留 0/kbdb empty_reason 5/UI 匯出診斷檔按鈕 1 順帶收 daemon agent 留下的 scan_dedup_scale_test.go(它沙盒推不了)。 親跑驗過不是空檔:TestScan_FormatDuplicate_EvanDatasetScale 10,545 個白名單內檔案(9,045 獨立 md + 500 組三格式撞 stem)耗時 688ms,PASS。 🔴 出貨時抓到兩個「用 staging 覆蓋 prod」的陷阱(已避開,記入 wiki): 1. rsync --delete 會砍掉 prod 才有的 daemon/(20 個安裝檔)與 README.md => 推上去封測者就下載不到 daemon。靠 git status 顯示 D 才抓到。 2. core 陣列會從 5 顆變 24 顆——prod 只裝 5 顆是懶載設計(其他用到才長)。 歷史警察指出 bbb433e 就是修「core 陣列被整個蓋掉」=> 同一個坑有前科,今天差點重演。 共同教訓:staging 與 prod 的內容範圍不一樣,不能整包蓋。 ⏸️ 安裝器部署(wrangler deploy --config)被 classifier 擋,等 leo 執行。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
73 lines
2.9 KiB
Go
73 lines
2.9 KiB
Go
// scan_dedup_scale_test.go — 同內容多格式去重在「真實規模」下的驗證(2026-08-07 驗收補測)。
|
||
//
|
||
// 為什麼要有這支:scan_dedup_test.go 只在 2~3 個檔案的小規模下驗證邏輯正確,
|
||
// 沒有驗過演算法在 leo 實據的規模(27,164 檔=9,045 md+9,044 json+9,043 html)下
|
||
// ①結果仍然正確(恰好 9,045 個 stem,一個 stem 只留一份)②不會因為規模爆炸而卡住
|
||
// (detectFormatDuplicates 是 map 分組+逐組排序,理論上是 O(n log n),這裡實測而非空想)。
|
||
package collector
|
||
|
||
import (
|
||
"fmt"
|
||
"testing"
|
||
"time"
|
||
)
|
||
|
||
func TestScan_FormatDuplicate_EvanDatasetScale(t *testing.T) {
|
||
if testing.Short() {
|
||
t.Skip("scale test skipped in -short mode")
|
||
}
|
||
root := t.TempDir()
|
||
const nStems = 9045 // leo 實據:9,045 md 為最大宗,json/html 各少於此數(非每個 md 都有 json/html 對應)
|
||
const nJSON = 9044
|
||
const nHTML = 9043
|
||
|
||
for i := 0; i < nStems; i++ {
|
||
writeFile(t, root, fmt.Sprintf("markdown/%05d.md", i), "md 內容", baseTime)
|
||
}
|
||
for i := 0; i < nJSON; i++ {
|
||
writeFile(t, root, fmt.Sprintf("json/%05d.json", i), "json 內容", baseTime)
|
||
}
|
||
for i := 0; i < nHTML; i++ {
|
||
writeFile(t, root, fmt.Sprintf("html/%05d.html", i), "html 內容", baseTime)
|
||
}
|
||
// .json/.html 不在 allowedExt 白名單裡(見 scan.go),不會進 current 候選集合——
|
||
// 白名單先擋掉非文件格式與「去重」是獨立的兩層。為了真的測到「三格式並存去重」,
|
||
// 額外補一批白名單內、彼此撞 stem 的三種格式(.md/.txt/.csv 皆在 allowedExt 內)。
|
||
const nTripleStem = 500
|
||
for i := 0; i < nTripleStem; i++ {
|
||
stem := fmt.Sprintf("triple-%05d", i)
|
||
writeFile(t, root, "a/"+stem+".md", "md", baseTime)
|
||
writeFile(t, root, "b/"+stem+".txt", "txt", baseTime)
|
||
writeFile(t, root, "c/"+stem+".csv", "csv,x", baseTime)
|
||
}
|
||
|
||
m := newTestManifest()
|
||
start := time.Now()
|
||
payload, err := Scan(root, m, ScanOptions{})
|
||
elapsed := time.Since(start)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
t.Logf("Scan() 於 %d 個白名單內檔案(%d 個獨立 md + %d 組三格式撞 stem)耗時 %v",
|
||
nStems+3*nTripleStem, nStems, nTripleStem, elapsed)
|
||
if elapsed > 30*time.Second {
|
||
t.Errorf("規模測試耗時 %v,超過可接受上限(可能有 O(n^2) 的迴歸)", elapsed)
|
||
}
|
||
|
||
added := 0
|
||
for _, ev := range payload.Events {
|
||
if ev.Type == "added" {
|
||
added++
|
||
}
|
||
}
|
||
// 期望:nStems 個獨立 md(彼此 stem 不同,不受去重影響)+ nTripleStem 個(三選一去重後只留一張)
|
||
wantAdded := nStems + nTripleStem
|
||
if added != wantAdded {
|
||
t.Fatalf("added 事件數=%d,want %d(去重後每個 triple stem 應只產生 1 個事件)", added, wantAdded)
|
||
}
|
||
if len(payload.DuplicateFormats) != 2*nTripleStem {
|
||
t.Fatalf("DuplicateFormats=%d,want %d(每個 triple stem 應有 2 份被標記為重複)",
|
||
len(payload.DuplicateFormats), 2*nTripleStem)
|
||
}
|
||
}
|