Wikilinks 與 backlinks:用算的,還是落表?答案是一半一半
花園的靈魂是 [[雙向連結]]——我在筆記裡寫 [[某篇的slug]],那篇筆記的頁尾自動長出「誰連到我」。實作上第一個要回答的問題:backlinks 是算出來的還是存起來的?
第一版:純用算的
語法解析是 domain 的純函式:從 body 抽出所有 wikilink slug。backlinks 就是反向索引——把所有已發佈筆記的出向連結掃一遍倒過來。筆記量小的時候這樣就夠了,而且零狀態、零漂移:真相永遠是 body 本身。
第二版:知識圖譜逼我落了半張表
圖譜頁需要「整張圖」——所有節點加所有邊。每次請求都全文掃描所有筆記做正則解析?那是拿 CPU 換懶惰。於是長出 note_links 邊表,但有兩條嚴格的紀律讓它保持「衍生快取」的身分:
- 只存解析結果(來源筆記、目標 slug),不烤發佈狀態——「有效的邊」由讀取端 join 已發佈筆記過濾。這樣發佈、下架、改標題都是零邊表操作,指向不存在筆記的「未發芽連結」也是合法資料。
- 重建只在一個地方:body 變動時由 repository 在同一個交易內原子重建該筆記的出向列。單一真相仍是 domain 的解析函式——邊表永遠可以全量重算回來。
漂移契約
衍生快取最怕的是有人繞過重建路徑直改資料。所以立了一條家規:內容寫入一律走 API,不准直接動 DB——手改 body 而不重建邊表,圖譜就會跟內文說不同的故事。這條契約便宜、有效,而且把「什麼情況下快取可信」說得明明白白。
事後看,這是一次教科書級的「先用算的、量級到了再物化」——順序如果反過來,就會在筆記只有二十篇的時候維護一張永遠對不齊的表。
讀到這裡若有一點收穫,替這顆種子澆一次水——匿名、一人一次。