Raxol.Core.Runtime.Plugins.DependencyManager (Raxol v0.4.0)

View Source

Manages plugin dependencies and dependency resolution. Provides sophisticated version constraint handling, efficient cycle detection, and detailed dependency chain reporting.

This module serves as the main entry point for dependency management functionality, delegating to specialized submodules for different aspects of the functionality:

  • DependencyManager.Core: Core dependency checking and load order resolution
  • DependencyManager.Version: Version parsing and constraint checking
  • DependencyManager.Graph: Dependency graph building and analysis
  • DependencyManager.Resolver: Load order resolution using Tarjan's algorithm

For more detailed documentation about the module's architecture and internals, see docs/dependency_manager.md.

Summary

Functions

Resolves the load order for a set of plugins based on their dependencies. Uses Tarjan's algorithm for efficient cycle detection and component identification.

Checks if a version meets a version requirement.

Types

dependency()

@type dependency() :: {String.t(), version_constraint()} | String.t()

dependency_chain()

@type dependency_chain() :: [String.t()]

dependency_error()

@type dependency_error() ::
  {:error, :missing_dependencies, [String.t()], dependency_chain()}
  | {:error, :version_mismatch,
     [{String.t(), String.t(), version_constraint()}], dependency_chain()}
  | {:error, :circular_dependency, [String.t()], dependency_chain()}

version_constraint()

@type version_constraint() :: String.t()

Functions

check_dependencies(plugin_id, plugin_metadata, loaded_plugins, dependency_chain \\ [])

Checks if a plugin's dependencies are satisfied.

Parameters

  • plugin_id - The ID of the plugin to check
  • plugin_metadata - The plugin's metadata containing its dependencies
  • loaded_plugins - Map of currently loaded plugins
  • dependency_chain - List of plugin IDs in the current dependency chain (for error reporting)

Returns

  • :ok - If all dependencies are satisfied
  • {:error, :missing_dependencies, missing, chain} - If any dependencies are missing
  • {:error, :version_mismatch, mismatches, chain} - If any dependencies have incompatible versions
  • {:error, :circular_dependency, cycle, chain} - If a circular dependency is detected

Examples

iex> DependencyManager.check_dependencies("my_plugin", %{dependencies: [{"other_plugin", ">= 1.0.0"}]}, %{"other_plugin" => %{version: "1.1.0"}}, [])
:ok

iex> DependencyManager.check_dependencies("my_plugin", %{dependencies: [{"missing_plugin", ">= 1.0.0"}]}, %{}, [])
{:error, :missing_dependencies, ["missing_plugin"], ["my_plugin"]}

iex> DependencyManager.check_dependencies("my_plugin", %{dependencies: [{"other_plugin", ">= 2.0.0"}]}, %{"other_plugin" => %{version: "1.0.0"}}, [])
{:error, :version_mismatch, [{"other_plugin", "1.0.0", ">= 2.0.0"}], ["my_plugin"]}

resolve_load_order(plugins)

Resolves the load order for a set of plugins based on their dependencies. Uses Tarjan's algorithm for efficient cycle detection and component identification.

Parameters

  • plugins - Map of plugin metadata, keyed by plugin ID

Returns

  • {:ok, load_order} - List of plugin IDs in the correct load order
  • {:error, :circular_dependency, cycle, chain} - If a circular dependency is detected

Examples

iex> DependencyManager.resolve_load_order(%{
  "plugin_a" => %{dependencies: [{"plugin_b", ">= 1.0.0"}]},
  "plugin_b" => %{dependencies: []}
})
{:ok, ["plugin_b", "plugin_a"]}

satisfies_version?(installed_version, version_req)

Checks if a version meets a version requirement.