Channel bridge discovery and lookup.
Provides a centralized registry for channel bridges, enabling runtime discovery of available channels, their capabilities, and associated adapters.
Usage
Register bridges at application startup:
# In your application.ex or a supervisor
BridgeRegistry.register(BridgePlugin.from_adapter(MyApp.TelegramAdapter))
BridgeRegistry.register(BridgePlugin.from_adapter(MyApp.DiscordAdapter))Query registered bridges:
BridgeRegistry.list_bridges()
BridgeRegistry.get_bridge(:telegram)
BridgeRegistry.capabilities(:telegram)Implementation
Uses an ETS table for storage, which provides fast concurrent reads. The table is created on first access and persists for the lifetime of the BEAM.
Summary
Functions
Loads bridge manifests and registers the resulting bridges with deterministic precedence.
Gets capabilities for a channel type.
Clears all registered bridges.
Gets an adapter module for a channel type and adapter kind.
Gets a channel module by its type.
Gets a bridge by its channel type.
Gets a bridge by its channel type, raising if not found.
Checks if a channel type supports a specific capability.
Lists all registered bridges.
Lists all channel types that have been registered.
Registers a bridge in the registry.
Unregisters a bridge from the registry.
Types
@type bootstrap_result() :: %{ registered_bridge_ids: [atom()], degraded_diagnostics: [manifest_diagnostic()], collision_diagnostics: [collision_diagnostic()] }
@type collision_diagnostic() :: %{ type: :bridge_id_collision, bridge_id: atom(), policy: manifest_collision_policy(), winning_path: String.t(), discarded_path: String.t() }
@type manifest_collision_policy() :: :prefer_first | :prefer_last
Functions
@spec bootstrap_from_manifests(keyword()) :: {:ok, bootstrap_result()} | {:error, {:fatal_required_bridge_error, manifest_diagnostic()}}
Loads bridge manifests and registers the resulting bridges with deterministic precedence.
Options
:manifest_paths- Manifest file paths, wildcard patterns, or directories.:required_bridges- Bridge IDs that must load successfully (atoms or strings).:collision_policy-:prefer_firstor:prefer_lastwhen bridge IDs collide.:clear_existing?- When true, clear the registry before registration.
Returns {:error, {:fatal_required_bridge_error, diagnostic}} for required failures.
Optional bridge failures degrade with warnings and telemetry.
Gets capabilities for a channel type.
Returns an empty list if the channel is not registered.
Examples
BridgeRegistry.capabilities(:telegram)
# => [:text, :image, :streaming]
BridgeRegistry.capabilities(:unknown)
# => []
@spec clear() :: :ok
Clears all registered bridges.
Primarily useful for testing.
Gets an adapter module for a channel type and adapter kind.
Examples
BridgeRegistry.get_adapter(:telegram, :mentions)
# => MyApp.TelegramMentionsAdapter
Gets a channel module by its type.
Returns nil if not registered.
Examples
BridgeRegistry.get_adapter_module(:telegram)
# => MyApp.TelegramAdapter
@spec get_bridge(atom()) :: Jido.Messaging.BridgePlugin.t() | nil
Gets a bridge by its channel type.
Examples
BridgeRegistry.get_bridge(:telegram)
# => %BridgePlugin{id: :telegram, ...}
BridgeRegistry.get_bridge(:unknown)
# => nil
@spec get_bridge!(atom()) :: Jido.Messaging.BridgePlugin.t()
Gets a bridge by its channel type, raising if not found.
Examples
BridgeRegistry.get_bridge!(:telegram)
# => %BridgePlugin{id: :telegram, ...}
BridgeRegistry.get_bridge!(:unknown)
# => ** (KeyError) bridge not found: :unknown
Checks if a channel type supports a specific capability.
Examples
BridgeRegistry.has_capability?(:telegram, :streaming)
# => true
@spec list_bridges() :: [Jido.Messaging.BridgePlugin.t()]
Lists all registered bridges.
Examples
BridgeRegistry.list_bridges()
# => [%BridgePlugin{id: :telegram, ...}, %BridgePlugin{id: :discord, ...}]
@spec list_channel_types() :: [atom()]
Lists all channel types that have been registered.
Examples
BridgeRegistry.list_channel_types()
# => [:telegram, :discord, :slack]
@spec register(Jido.Messaging.BridgePlugin.t()) :: :ok
Registers a bridge in the registry.
If a bridge with the same ID already exists, it will be replaced.
Examples
bridge = BridgePlugin.from_adapter(MyApp.TelegramAdapter)
BridgeRegistry.register(bridge)
# => :ok
@spec unregister(atom()) :: :ok
Unregisters a bridge from the registry.
Examples
BridgeRegistry.unregister(:telegram)
# => :ok