Behaviour for OKF graph backends.
Backends turn a loaded ExOKF.Bundle into a traversable directed graph whose
nodes are concept ids and whose edges come from internal markdown links.
The native adjacency backend ships in v0.1. The GraphBLAS backend is an ExOKF extension (not part of the OKF standard); full sparse acceleration lands in v0.2.
Types
graph/0— opaque backend-specific graph structureconcept_id/0— OKF concept id (String.t()), e.g."tables/orders"
Example implementation
A minimal adjacency-style backend:
defmodule MyApp.TinyGraph do
@behaviour ExOKF.Graph.Backend
@impl true
def build(%ExOKF.Bundle{} = bundle) do
# Build your representation from bundle.concepts and their links
ExOKF.Graph.Adjacency.build(bundle)
end
@impl true
def neighbors(graph, id), do: ExOKF.Graph.Adjacency.neighbors(graph, id)
@impl true
def reverse_neighbors(graph, id), do: ExOKF.Graph.Adjacency.reverse_neighbors(graph, id)
@impl true
def reachable(graph, id, opts \\ []), do: ExOKF.Graph.Adjacency.reachable(graph, id, opts)
@impl true
def has_edge?(graph, from, to), do: ExOKF.Graph.Adjacency.has_edge?(graph, from, to)
@impl true
def edges(graph), do: ExOKF.Graph.Adjacency.edges(graph)
@impl true
def node_count(graph), do: ExOKF.Graph.Adjacency.node_count(graph)
@impl true
def edge_count(graph), do: ExOKF.Graph.Adjacency.edge_count(graph)
endThen select it when indexing:
bundle = ExOKF.Graph.index(bundle, MyApp.TinyGraph)
ExOKF.Graph.neighbors(bundle, "tables/orders")
Summary
Types
OKF concept identifier — the file path within the bundle with .md removed.
Opaque graph structure owned by a backend.
Callbacks
Builds a graph from the bundle's concepts and internal links.
Returns the number of directed edges in the graph.
Returns all directed edges as {from, to} tuples, sorted.
Returns true when a directed edge from → to exists.
Returns sorted outbound neighbor concept ids of id.
Returns the number of concept nodes in the graph.
Returns concept ids reachable from id.
Returns sorted inbound neighbor concept ids (backlinks) of id.
Types
@type concept_id() :: String.t()
OKF concept identifier — the file path within the bundle with .md removed.
Examples
"tables/orders"
"datasets/sales"
"playbooks/incident-response"
@type graph() :: term()
Opaque graph structure owned by a backend.
Concrete shapes include ExOKF.Graph.Adjacency.t() and
ExOKF.Graph.GraphBLAS.t(). Callers should treat this as an opaque term().
Callbacks
@callback build(ExOKF.Bundle.t()) :: graph()
Builds a graph from the bundle's concepts and internal links.
Parameters
bundle(ExOKF.Bundle.t()) — loaded OKF bundle
Returns
A backend-specific graph/0 value later passed to the other callbacks.
Example
@impl true
def build(%ExOKF.Bundle{} = bundle) do
ExOKF.Graph.Adjacency.build(bundle)
end
@callback edge_count(graph()) :: non_neg_integer()
Returns the number of directed edges in the graph.
Parameters
Example
@impl true
def edge_count(graph), do: ExOKF.Graph.Adjacency.edge_count(graph)
@callback edges(graph()) :: [{concept_id(), concept_id()}]
Returns all directed edges as {from, to} tuples, sorted.
Parameters
Returns
Example: [{"tables/orders", "tables/customers"}, {"tables/orders", "datasets/sales"}].
Example
@impl true
def edges(graph), do: ExOKF.Graph.Adjacency.edges(graph)
@callback has_edge?(graph(), concept_id(), concept_id()) :: boolean()
Returns true when a directed edge from → to exists.
Parameters
graph(graph/0) — graph frombuild/1from(concept_id/0) — edge sourceto(concept_id/0) — edge target
Example
@impl true
def has_edge?(graph, from, to) do
ExOKF.Graph.Adjacency.has_edge?(graph, from, to)
end
@callback neighbors(graph(), concept_id()) :: [concept_id()]
Returns sorted outbound neighbor concept ids of id.
Parameters
graph(graph/0) — graph frombuild/1id(concept_id/0) — source concept id
Returns
A list of concept ids, e.g. ["datasets/sales", "tables/customers"].
Example
@impl true
def neighbors(graph, id), do: ExOKF.Graph.Adjacency.neighbors(graph, id)
@callback node_count(graph()) :: non_neg_integer()
Returns the number of concept nodes in the graph.
Parameters
Example
@impl true
def node_count(graph), do: ExOKF.Graph.Adjacency.node_count(graph)
@callback reachable(graph(), concept_id(), keyword()) :: [concept_id()]
Returns concept ids reachable from id.
Parameters
graph(graph/0) — graph frombuild/1id(concept_id/0) — start concept idopts(keyword()) — supported options::max_depth(pos_integer() \| :infinity) — hop limit (default:infinity):include_self(boolean()) — includeidin the result (defaultfalse)
Returns
A sorted list of reachable concept ids.
Example
@impl true
def reachable(graph, id, opts \\ []) do
ExOKF.Graph.Adjacency.reachable(graph, id, opts)
end
@callback reverse_neighbors(graph(), concept_id()) :: [concept_id()]
Returns sorted inbound neighbor concept ids (backlinks) of id.
Parameters
graph(graph/0) — graph frombuild/1id(concept_id/0) — target concept id
Returns
A list of concept ids that link to id.
Example
@impl true
def reverse_neighbors(graph, id) do
ExOKF.Graph.Adjacency.reverse_neighbors(graph, id)
end