Clarity.Introspector behaviour (Clarity v0.5.1)

Copy Markdown View Source

Defines the behaviour and orchestration logic for introspectors.

Clarity introspects ash applications using an underlying :digraph structure, allowing visualization and exploration of resources, domains, actions, types, and more.

This module defines the Clarity.Introspector behaviour and the default pipeline for built-in and user-defined introspectors. Each introspector processes vertices individually through the introspect_vertex/2 callback.

Custom Introspectors

Introspector configuration is managed by Clarity.Config. See the documentation for Clarity.Config for detailed configuration options and examples.

Example

Here's a simplified example of a custom introspector implementation:

defmodule MyApp.MyCustomIntrospector do
  @behaviour Clarity.Introspector

  alias Clarity.Vertex

  @impl Clarity.Introspector
  def source_vertex_types, do: [Vertex.Module]

  @impl Clarity.Introspector
  def introspect_vertex(%Vertex.Module{module: module} = module_vertex, _graph) do
    # Create a custom vertex for the module
    custom_vertex = %Vertex.Custom{module: module}

    [
      {:vertex, custom_vertex},
      {:edge, module_vertex, custom_vertex, :custom}
    ]
  end

  def introspect_vertex(_vertex, _graph), do: []
end

Summary

Types

An introspection entry returned by introspectors.

t()

A module implementing the Clarity.Introspector behaviour.

Callbacks

Performs introspection on a single vertex in the async system.

Returns the list of vertex types this introspector can process.

Types

entry()

@type entry() ::
  {:vertex, Clarity.Vertex.t()}
  | {:edge, Clarity.Vertex.t(), Clarity.Vertex.t(), term()}
  | {:purge, Clarity.Vertex.t()}

An introspection entry returned by introspectors.

  • {:vertex, vertex} - Adds a new vertex to the graph
  • {:edge, from_vertex, to_vertex, label} - Adds an edge between vertices
  • {:purge, vertex} - Removes a vertex and all vertices caused by it

Warning - Internal API

The {:purge, vertex} entry type is for internal use by Clarity's Application and Module introspectors only. Custom introspectors must not emit purge entries.

result()

@type result() :: {:ok, [entry()]} | {:error, :unmet_dependencies | term()}

t()

@type t() :: module()

A module implementing the Clarity.Introspector behaviour.

Callbacks

introspect_vertex(vertex, graph)

@callback introspect_vertex(vertex :: Clarity.Vertex.t(), graph :: Clarity.Graph.t()) ::
  result()

Performs introspection on a single vertex in the async system.

This callback is called by workers for each vertex that needs to be processed. The introspector receives the vertex to process and a read-only view of the current graph state for context.

Returns {:ok, results} on success, where results is a list of {:vertex, vertex} and {:edge, from_vertex, to_vertex, label} tuples to add to the graph.

If the introspector cannot run due to missing dependencies in the graph (such as an Ash resource referencing a domain that hasn't been introspected yet), it should return :missing_dependencies. The worker will re-queue the task to be retried later, allowing other introspectors to run first and potentially satisfy the dependencies.

If an unexpected error occurs, return {:error, reason}. The worker will log the error and acknowledge the task to prevent infinite retries.

source_vertex_types()

@callback source_vertex_types() :: [module()]

Returns the list of vertex types this introspector can process.

This is used to filter which introspectors should be run for each vertex type, improving performance by avoiding unnecessary task creation.