Nous.KnowledgeBase.Store behaviour (nous v0.15.7)
View SourceStorage behaviour for knowledge base backends.
Defines callbacks for document, entry, and link CRUD operations
plus search and graph traversal. Follows the same pattern as
Nous.Memory.Store but with wiki-specific operations.
All list/search callbacks accept a :kb_id option for scoping.
State threading caveat
Several call sites (kb_link, persist_to_store) read store_state
once and reuse it across multiple write callbacks. This is safe for
backends where state is a mutable handle (the included ETS impl,
any process-wrapped backend) but NOT for purely-functional stores
that depend on threading the new state through every call. New
backends must either:
- use mutable handles in
state(ETS / process registry / database connection ref), OR - implement their own concurrency control / write log (the kb code cannot guarantee atomicity across multi-step operations).
This contract may tighten in a future version; for now, prefer mutable-handle backends.
Summary
Callbacks
Optional bulk callback for getting all link counts grouped by source entry.
Callbacks
@callback backlinks(state :: term(), entry_id :: String.t()) :: {:ok, [Nous.KnowledgeBase.Link.t()]}
@callback fetch_document(state :: term(), id :: String.t()) :: {:ok, Nous.KnowledgeBase.Document.t()} | {:error, :not_found}
@callback fetch_entry(state :: term(), id :: String.t()) :: {:ok, Nous.KnowledgeBase.Entry.t()} | {:error, :not_found}
@callback fetch_entry_by_slug(state :: term(), slug :: String.t()) :: {:ok, Nous.KnowledgeBase.Entry.t()} | {:error, :not_found}
@callback link_counts_by_source(state :: term()) :: {:ok, %{optional(String.t()) => non_neg_integer()}}
Optional bulk callback for getting all link counts grouped by source entry.
Backends that can answer "for every entry, how many outgoing links does
it have?" with a single scan should implement this for O(L) instead of
O(E*L) health checks. Falls back to per-entry outlinks/2 when not
implemented (the default in the macro below). Returns
{:ok, %{entry_id => count}}.
@callback list_documents(state :: term(), opts :: keyword()) :: {:ok, [Nous.KnowledgeBase.Document.t()]}
@callback list_entries(state :: term(), opts :: keyword()) :: {:ok, [Nous.KnowledgeBase.Entry.t()]}
@callback outlinks(state :: term(), entry_id :: String.t()) :: {:ok, [Nous.KnowledgeBase.Link.t()]}
@callback search_entries(state :: term(), query :: String.t(), opts :: keyword()) :: {:ok, [{Nous.KnowledgeBase.Entry.t(), float()}]}
@callback store_document(state :: term(), doc :: Nous.KnowledgeBase.Document.t()) :: {:ok, term()} | {:error, term()}
@callback store_entry(state :: term(), entry :: Nous.KnowledgeBase.Entry.t()) :: {:ok, term()} | {:error, term()}
@callback store_link(state :: term(), link :: Nous.KnowledgeBase.Link.t()) :: {:ok, term()} | {:error, term()}