TantivyEx.Distributed.OTP (TantivyEx v0.4.1)

View Source

OTP-based distributed search API for TantivyEx.

This module provides a clean, OTP-native interface for distributed search operations, leveraging Elixir's supervision trees, GenServers, and fault tolerance mechanisms instead of native coordination.

Features

  • Supervisor-based fault tolerance
  • GenServer per search node
  • Registry-based node discovery
  • Task supervision for concurrent operations
  • Built-in health monitoring
  • Automatic failover and recovery

Example Usage

# Start the distributed search system
{:ok, _pid} = TantivyEx.Distributed.OTP.start_link()

# Add search nodes
:ok = TantivyEx.Distributed.OTP.add_node("node1", "local://index1", 1.0)
:ok = TantivyEx.Distributed.OTP.add_node("node2", "local://index2", 1.5)

# Configure behavior
:ok = TantivyEx.Distributed.OTP.configure(%{
  timeout_ms: 5000,
  merge_strategy: :score_desc
})

# Perform distributed search
{:ok, results} = TantivyEx.Distributed.OTP.search("query text", 10, 0)

Summary

Functions

Add a search node to the distributed cluster.

Add multiple nodes at once.

Configure the distributed search behavior.

Get list of active node IDs.

Get cluster statistics and health information.

Get detailed statistics for a specific node.

Remove a search node from the cluster.

Check if the distributed search system is running.

Perform a distributed search across the cluster.

Set a node's active/inactive status.

Perform a simple distributed search with sensible defaults.

Start the distributed search system.

Stop the distributed search system.

Types

config()

@type config() :: %{
  timeout_ms: non_neg_integer(),
  max_retries: non_neg_integer(),
  merge_strategy: merge_strategy(),
  load_balancing: load_balancing_strategy(),
  health_check_interval: non_neg_integer()
}

load_balancing_strategy()

@type load_balancing_strategy() ::
  :round_robin | :weighted_round_robin | :least_connections | :health_based

merge_strategy()

@type merge_strategy() :: :score_desc | :score_asc | :node_order | :round_robin

Functions

add_node(node_id, endpoint, weight, opts \\ [])

@spec add_node(String.t(), String.t(), float(), keyword()) :: :ok | {:error, term()}

Add a search node to the distributed cluster.

Parameters

  • node_id - Unique identifier for the node
  • endpoint - Endpoint specification (e.g., "local://path", "http://host:port")
  • weight - Weight for load balancing (must be > 0.0)
  • opts - Additional options

Examples

:ok = TantivyEx.Distributed.OTP.add_node("node1", "local://index1", 1.0)
:ok = TantivyEx.Distributed.OTP.add_node("node2", "http://remote:9200", 2.0)

add_nodes(nodes, opts \\ [])

@spec add_nodes(
  [{String.t(), String.t(), float()}],
  keyword()
) :: :ok | {:error, term()}

Add multiple nodes at once.

Parameters

  • nodes - List of {node_id, endpoint, weight} tuples
  • opts - Additional options

Examples

nodes = [
  {"node1", "local://index1", 1.0},
  {"node2", "local://index2", 1.5},
  {"node3", "http://remote:9200", 2.0}
]

:ok = TantivyEx.Distributed.OTP.add_nodes(nodes)

configure(config, opts \\ [])

@spec configure(
  config(),
  keyword()
) :: :ok | {:error, term()}

Configure the distributed search behavior.

Configuration Options

  • :timeout_ms - Request timeout in milliseconds (default: 5000)
  • :max_retries - Maximum retries for failed requests (default: 3)
  • :merge_strategy - Result merging strategy (default: :score_desc)
  • :load_balancing - Load balancing strategy (default: :weighted_round_robin)
  • :health_check_interval - Health check interval in ms (default: 30000)

Examples

:ok = TantivyEx.Distributed.OTP.configure(%{
  timeout_ms: 10_000,
  merge_strategy: :score_desc,
  health_check_interval: 60_000
})

get_active_nodes(opts \\ [])

@spec get_active_nodes(keyword()) :: {:ok, [String.t()]}

Get list of active node IDs.

Examples

{:ok, nodes} = TantivyEx.Distributed.OTP.get_active_nodes()
# => {:ok, ["node1", "node2"]}

get_cluster_stats(opts \\ [])

@spec get_cluster_stats(keyword()) :: {:ok, map()}

Get cluster statistics and health information.

Returns

A map containing:

  • :total_nodes - Total number of configured nodes
  • :active_nodes - Number of currently active nodes
  • :inactive_nodes - Number of inactive nodes
  • :config - Current configuration
  • :cluster_stats - Performance statistics

Examples

{:ok, stats} = TantivyEx.Distributed.OTP.get_cluster_stats()
IO.puts "Active nodes: #{stats.active_nodes}/#{stats.total_nodes}"

get_node_stats(node_id, opts \\ [])

@spec get_node_stats(
  String.t(),
  keyword()
) :: {:ok, map()} | {:error, term()}

Get detailed statistics for a specific node.

Parameters

  • node_id - Unique identifier for the node
  • opts - Additional options

Examples

{:ok, stats} = TantivyEx.Distributed.OTP.get_node_stats("node1")

remove_node(node_id, opts \\ [])

@spec remove_node(
  String.t(),
  keyword()
) :: :ok | {:error, term()}

Remove a search node from the cluster.

Parameters

  • node_id - Unique identifier for the node to remove
  • opts - Additional options

Examples

:ok = TantivyEx.Distributed.OTP.remove_node("node1")

running?(opts \\ [])

@spec running?(keyword()) :: boolean()

Check if the distributed search system is running.

Examples

true = TantivyEx.Distributed.OTP.running?()

search(query, limit, offset, opts \\ [])

@spec search(
  String.t() | reference(),
  non_neg_integer(),
  non_neg_integer(),
  keyword()
) ::
  {:ok, map()} | {:error, term()}

Perform a distributed search across the cluster.

Parameters

  • query - Search query (string or compiled query reference)
  • limit - Maximum number of results to return
  • offset - Number of results to skip for pagination
  • opts - Additional options

Examples

{:ok, results} = TantivyEx.Distributed.OTP.search("rust programming", 20, 0)

# With options
{:ok, results} = TantivyEx.Distributed.OTP.search(
  "rust programming",
  20,
  0,
  coordinator: MyApp.Coordinator
)

set_node_status(node_id, active, opts \\ [])

@spec set_node_status(String.t(), boolean(), keyword()) :: :ok | {:error, term()}

Set a node's active/inactive status.

Inactive nodes will not receive search requests.

Parameters

  • node_id - Unique identifier for the node
  • active - Whether the node should be active
  • opts - Additional options

Examples

:ok = TantivyEx.Distributed.OTP.set_node_status("node1", false)
:ok = TantivyEx.Distributed.OTP.set_node_status("node1", true)

simple_search(query, opts \\ [])

@spec simple_search(
  String.t(),
  keyword()
) :: {:ok, map()} | {:error, term()}

Perform a simple distributed search with sensible defaults.

This is a convenience function for basic searches.

Examples

{:ok, results} = TantivyEx.Distributed.OTP.simple_search("rust programming")

start_link(opts \\ [])

@spec start_link(keyword()) :: {:ok, pid()} | {:error, term()}

Start the distributed search system.

This starts the supervision tree and all necessary processes.

Options

  • :name - Name for the main supervisor (default: TantivyEx.Distributed.Supervisor)
  • :coordinator_name - Name for the coordinator GenServer
  • :registry_name - Name for the node registry

Examples

{:ok, pid} = TantivyEx.Distributed.OTP.start_link()
{:ok, pid} = TantivyEx.Distributed.OTP.start_link(name: MyApp.DistributedSearch)

stop(opts \\ [])

@spec stop(keyword()) :: :ok

Stop the distributed search system.

This will gracefully shut down all nodes and supervisors.

Examples

:ok = TantivyEx.Distributed.OTP.stop()