From 158907f36abd39ffc7448ba6f795d8d7ce44b1f6 Mon Sep 17 00:00:00 2001 From: AI Engineer Date: Sat, 16 May 2026 01:07:42 +0800 Subject: [PATCH] refactor: standardize Hook signatures to use *Document --- CHANGELOG.md | 5 +++++ README.md | 14 ++++++------ doc.go | 60 ++++++++++++++++++++++++++++++---------------------- doc_test.go | 6 +++--- 4 files changed, 50 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3126fc8..07ad5d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## v1.0.9 (2026-05-16) +- **Hook 系统重构**: + - **参数标准化**: `Hooks` 结构体中的所有回调函数(`OnUpdatedDoc`, `OnRemovedDoc`, `OnUpdatedToC`, `OnRemovedToC`)现在统一接收 `*Document` 对象作为参数,极大地方便了外部处理逻辑直接获取文档元数据与路径。 + - **触发逻辑对齐**: 确保在文档删除、重命名及 ToC 更新时,钩子都能正确获取到相关的文档上下文。 + ## [1.0.0] - 2026-05-15 ### Added - 从 `knowbase` 项目剥离生成的独立 `docDB` 项目。 diff --git a/README.md b/README.md index 5fd36f1..a95e6db 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# @go/docDB +# @go/docDB v1.0.9 `docDB` 是一个独立的高级文档存储引擎,基于 `@go/tableDB` 构建,提供全自动版本管理、历史存证、流式大文件处理及精细化生命周期钩子。 @@ -38,27 +38,27 @@ db := engine.Auth("user_123") - **`SetDoc(doc *Document) error`**:保存文档,提升版本。触发 `OnUpdatedDoc` 和 `OnUpdatedToC`。 - **`SetMeta(path string, meta map[string]any) error`**:更新元数据,**不提升版本**。若包含 `textContent` 且为 Markdown,会自动触发 `OnRemovedToC` 和 `OnUpdatedToC`。 -- **`Move(oldPath, newPath string) error`**:重命名。触发 `OnRemovedDoc(oldPath)` -> `OnUpdatedDoc(newPath)`。 +- **`Move(oldPath, newPath string) error`**:重命名。触发 `OnRemovedDoc(oldDoc)` -> `OnUpdatedDoc(newDoc)`。 - **`Get(path string) (*Document, error)`**:获取最新版。 - **`GetByVersion(path string, version uint64) (*Document, error)`**:获取历史版(含已删除)。 -- **`Remove(path string) error`**:删除文档。触发 `OnRemovedDoc`。 +- **`Remove(path string) error`**:删除文档。触发 `OnRemovedDoc(doc)`。 ### 3. 生命周期钩子 (Hooks) ```go -// 文档级事件 +// 所有 Hook 统一返回 *Document 对象,方便外部获取 Path, ToC, Metadata 等完整上下文 engine.Hooks.OnUpdatedDoc = func(doc *docDB.Document) { // 文档创建或内容更新时触发 (SetDoc 或 Move 触发) } -engine.Hooks.OnRemovedDoc = func(path string) { +engine.Hooks.OnRemovedDoc = func(doc *docDB.Document) { // 文档被物理删除或 Move 移除旧路径时触发 } // 目录(ToC)级事件 -engine.Hooks.OnUpdatedToC = func(path string, toc []docDB.ToCNode) { +engine.Hooks.OnUpdatedToC = func(doc *docDB.Document) { // 目录生成或变更时触发 } -engine.Hooks.OnRemovedToC = func(path string) { +engine.Hooks.OnRemovedToC = func(doc *docDB.Document) { // 目录失效时触发 } ``` diff --git a/doc.go b/doc.go index 8a4aa26..40b5435 100644 --- a/doc.go +++ b/doc.go @@ -16,9 +16,9 @@ import ( // Hooks 生命周期钩子 type Hooks struct { OnUpdatedDoc func(doc *Document) - OnRemovedDoc func(path string) - OnUpdatedToC func(path string, toc []ToCNode) - OnRemovedToC func(path string) + OnRemovedDoc func(doc *Document) + OnUpdatedToC func(doc *Document) + OnRemovedToC func(doc *Document) } // DocDBUnauthorized 实例 @@ -135,7 +135,7 @@ func (a *DocDB) SetDoc(docObj *Document) error { var internalID string if existing != nil { - a.triggerRemovedToC(docObj.Path) + a.triggerRemovedToC(a.toDoc(existing)) a.archive(existing) internalID = cast.String(existing["id"]) docObj.Version = cast.Uint64(existing["version"]) + 1 @@ -168,7 +168,7 @@ func (a *DocDB) SetDoc(docObj *Document) error { if err == nil { a.triggerUpdatedDoc(docObj) if docObj.ToC != nil { - a.triggerUpdatedToC(docObj.Path, docObj.ToC) + a.triggerUpdatedToC(docObj) } } return err @@ -185,10 +185,9 @@ func (a *DocDB) SetMeta(path string, meta map[string]any) error { if text, ok := meta["textContent"].(string); ok { docType := cast.String(existing["type"]) if docType == "markdown" || strings.HasSuffix(strings.ToLower(path), ".md") { - a.triggerRemovedToC(path) + a.triggerRemovedToC(a.toDoc(existing)) newToC := ExtractToC(text) meta["toc"] = newToC - a.triggerUpdatedToC(path, newToC) } } @@ -196,7 +195,11 @@ func (a *DocDB) SetMeta(path string, meta map[string]any) error { existing[k] = v } - return a.table.Set(existing) + err = a.table.Set(existing) + if err == nil && meta["toc"] != nil { + a.triggerUpdatedToC(a.toDoc(existing)) + } + return err } // Move 修改路径 (重命名) @@ -207,9 +210,10 @@ func (a *DocDB) Move(oldPath, newPath string) error { } // 触发删除旧路径事件 - a.triggerRemovedDoc(oldPath) + oldDoc := a.toDoc(existing) + a.triggerRemovedDoc(oldDoc) if existing["toc"] != nil { - a.triggerRemovedToC(oldPath) + a.triggerRemovedToC(oldDoc) } existing["path"] = newPath @@ -219,7 +223,7 @@ func (a *DocDB) Move(oldPath, newPath string) error { if newDoc != nil { a.triggerUpdatedDoc(newDoc) if newDoc.ToC != nil { - a.triggerUpdatedToC(newPath, newDoc.ToC) + a.triggerUpdatedToC(newDoc) } } } @@ -234,6 +238,15 @@ func (a *DocDB) getRaw(path string) (map[string]any, error) { return res[0], nil } +func (a *DocDB) toDoc(record map[string]any) *Document { + if record == nil { + return nil + } + var doc Document + cast.Convert(&doc, record) + return &doc +} + func (a *DocDB) archive(existing map[string]any) { histRecord := make(map[string]any) for k, v := range existing { @@ -284,9 +297,7 @@ func (a *DocDB) Get(path string) (*Document, error) { if err != nil || res == nil { return nil, err } - var doc Document - cast.Convert(&doc, res) - return &doc, nil + return a.toDoc(res), nil } // GetByVersion 按版本获取文档 @@ -316,9 +327,7 @@ func (a *DocDB) GetByVersion(path string, version uint64) (*Document, error) { return nil, err } - var doc Document - cast.Convert(&doc, histRes[0]) - return &doc, nil + return a.toDoc(histRes[0]), nil } // Remove 删除文档 (自动保存最后一版到历史) @@ -328,9 +337,10 @@ func (a *DocDB) Remove(path string) error { return nil } - a.triggerRemovedDoc(path) + doc := a.toDoc(existing) + a.triggerRemovedDoc(doc) if existing["toc"] != nil { - a.triggerRemovedToC(path) + a.triggerRemovedToC(doc) } a.archive(existing) @@ -343,21 +353,21 @@ func (a *DocDB) triggerUpdatedDoc(doc *Document) { } } -func (a *DocDB) triggerRemovedDoc(path string) { +func (a *DocDB) triggerRemovedDoc(doc *Document) { if a.parent.Hooks.OnRemovedDoc != nil { - a.parent.Hooks.OnRemovedDoc(path) + a.parent.Hooks.OnRemovedDoc(doc) } } -func (a *DocDB) triggerUpdatedToC(path string, toc []ToCNode) { +func (a *DocDB) triggerUpdatedToC(doc *Document) { if a.parent.Hooks.OnUpdatedToC != nil { - a.parent.Hooks.OnUpdatedToC(path, toc) + a.parent.Hooks.OnUpdatedToC(doc) } } -func (a *DocDB) triggerRemovedToC(path string) { +func (a *DocDB) triggerRemovedToC(doc *Document) { if a.parent.Hooks.OnRemovedToC != nil { - a.parent.Hooks.OnRemovedToC(path) + a.parent.Hooks.OnRemovedToC(doc) } } diff --git a/doc_test.go b/doc_test.go index ab079db..679f707 100644 --- a/doc_test.go +++ b/doc_test.go @@ -21,9 +21,9 @@ func TestDocDB(t *testing.T) { var updatedCalled, removedDocCalled, updatedToCCalled, removedToCCalled bool docDBInst.Hooks.OnUpdatedDoc = func(doc *Document) { updatedCalled = true } - docDBInst.Hooks.OnRemovedDoc = func(path string) { removedDocCalled = true } - docDBInst.Hooks.OnUpdatedToC = func(path string, toc []ToCNode) { updatedToCCalled = true } - docDBInst.Hooks.OnRemovedToC = func(path string) { removedToCCalled = true } + docDBInst.Hooks.OnRemovedDoc = func(doc *Document) { removedDocCalled = true } + docDBInst.Hooks.OnUpdatedToC = func(doc *Document) { updatedToCCalled = true } + docDBInst.Hooks.OnRemovedToC = func(doc *Document) { removedToCCalled = true } // 1. 测试 SetDoc (创建) docPath := "/test/doc1.md"