Behaviour for Jido.Messaging storage adapters.
Adapters provide persistence for rooms, participants, threads, and messages. Each adapter instance maintains its own state (e.g., ETS table references) to enable multiple isolated messaging instances in the same BEAM.
Implementing an Adapter
defmodule MyApp.CustomAdapter do
@behaviour Jido.Messaging.Persistence
@impl true
def init(opts) do
# Initialize adapter state
{:ok, %{}}
end
# ... implement other callbacks
end
Summary
Callbacks
Create a binding between an internal room and an external platform room.
Delete bridge config.
Delete stored ingress subscription metadata.
Delete a message by ID
Delete a participant by ID
Delete a room by ID
Delete a room binding by ID.
Delete routing policy by room id.
Lookup a single directory entry by target and query.
Search directory entries by target and query.
Fetch bridge config by id.
Get a message by ID
Get a message by its external ID within a channel/instance context.
Get messages for a room with options (limit, before, after)
Fetch onboarding flow state by onboarding ID.
Get or create a participant by external ID.
Get or create a room by external binding.
Get a participant by ID
Get a room by ID
Get a room by its external binding.
Fetch routing policy by room id.
Get a thread by ID
Get a thread by room and external thread ID
Get a thread by root message ID
Initialize the adapter with options. Returns adapter state.
List bridge configs with optional filters.
List stored ingress subscription metadata for a bridge.
List all bindings for a room.
List rooms with optional filters
List threads for a room
Persist bridge config.
Persist normalized ingress subscription metadata.
Save a message
Persist onboarding flow state.
Save a participant (insert or update)
Save a room (insert or update)
Persist routing policy.
Save a thread
Update a message's external_id after successful channel delivery.
Types
@type bridge_id() :: String.t()
@type channel() :: atom()
@type directory_query() :: map()
@type directory_target() :: :participant | :room
@type external_id() :: String.t()
@type message_id() :: String.t()
@type onboarding_flow() :: map()
@type onboarding_id() :: String.t()
@type participant_id() :: String.t()
@type room_id() :: String.t()
@type state() :: term()
Callbacks
@callback create_room_binding( state(), room_id(), channel(), bridge_id(), external_id(), attrs :: map() ) :: {:ok, Jido.Messaging.RoomBinding.t()} | {:error, term()}
Create a binding between an internal room and an external platform room.
Delete bridge config.
@callback delete_ingress_subscription(state(), bridge_id(), String.t()) :: :ok | {:error, :not_found}
Delete stored ingress subscription metadata.
@callback delete_message(state(), message_id()) :: :ok | {:error, term()}
Delete a message by ID
@callback delete_participant(state(), participant_id()) :: :ok | {:error, term()}
Delete a participant by ID
Delete a room by ID
Delete a room binding by ID.
Delete routing policy by room id.
@callback directory_lookup( state(), directory_target(), directory_query(), opts :: keyword() ) :: {:ok, map()} | {:error, :not_found | {:ambiguous, [map()]} | term()}
Lookup a single directory entry by target and query.
Returns {:error, {:ambiguous, matches}} when multiple entries satisfy the query.
@callback directory_search( state(), directory_target(), directory_query(), opts :: keyword() ) :: {:ok, [map()]} | {:error, term()}
Search directory entries by target and query.
@callback get_bridge_config(state(), String.t()) :: {:ok, Jido.Messaging.BridgeConfig.t()} | {:error, :not_found}
Fetch bridge config by id.
@callback get_message(state(), message_id()) :: {:ok, Jido.Messaging.Message.t()} | {:error, :not_found}
Get a message by ID
@callback get_message_by_external_id(state(), channel(), bridge_id(), external_id()) :: {:ok, Jido.Messaging.Message.t()} | {:error, :not_found}
Get a message by its external ID within a channel/instance context.
Used for resolving reply_to references from external platforms.
@callback get_messages(state(), room_id(), opts :: keyword()) :: {:ok, [Jido.Messaging.Message.t()]}
Get messages for a room with options (limit, before, after)
@callback get_onboarding(state(), onboarding_id()) :: {:ok, onboarding_flow()} | {:error, :not_found}
Fetch onboarding flow state by onboarding ID.
@callback get_or_create_participant_by_external_id( state(), channel(), external_id(), attrs :: map() ) :: {:ok, Jido.Chat.Participant.t()}
Get or create a participant by external ID.
Used when receiving messages from external channels to map external user IDs to internal participant IDs.
@callback get_or_create_room_by_external_binding( state(), channel(), bridge_id(), external_id(), attrs :: map() ) :: {:ok, Jido.Chat.Room.t()}
Get or create a room by external binding.
Used when receiving messages from external channels to map external chat IDs to internal room IDs.
@callback get_participant(state(), participant_id()) :: {:ok, Jido.Chat.Participant.t()} | {:error, :not_found}
Get a participant by ID
@callback get_room(state(), room_id()) :: {:ok, Jido.Chat.Room.t()} | {:error, :not_found}
Get a room by ID
@callback get_room_by_external_binding(state(), channel(), bridge_id(), external_id()) :: {:ok, Jido.Chat.Room.t()} | {:error, :not_found}
Get a room by its external binding.
Returns the room if a binding exists, otherwise :not_found.
@callback get_routing_policy(state(), String.t()) :: {:ok, Jido.Messaging.RoutingPolicy.t()} | {:error, :not_found}
Fetch routing policy by room id.
@callback get_thread(state(), String.t()) :: {:ok, Jido.Messaging.Thread.t()} | {:error, :not_found}
Get a thread by ID
@callback get_thread_by_external_id(state(), room_id(), String.t()) :: {:ok, Jido.Messaging.Thread.t()} | {:error, :not_found}
Get a thread by room and external thread ID
@callback get_thread_by_root_message(state(), room_id(), message_id()) :: {:ok, Jido.Messaging.Thread.t()} | {:error, :not_found}
Get a thread by root message ID
Initialize the adapter with options. Returns adapter state.
@callback list_bridge_configs( state(), keyword() ) :: {:ok, [Jido.Messaging.BridgeConfig.t()]}
List bridge configs with optional filters.
@callback list_ingress_subscriptions(state(), bridge_id(), keyword()) :: {:ok, [Jido.Messaging.IngressSubscription.t()]}
List stored ingress subscription metadata for a bridge.
@callback list_room_bindings(state(), room_id()) :: {:ok, [Jido.Messaging.RoomBinding.t()]}
List all bindings for a room.
@callback list_rooms(state(), opts :: keyword()) :: {:ok, [Jido.Chat.Room.t()]}
List rooms with optional filters
@callback list_threads(state(), room_id(), opts :: keyword()) :: {:ok, [Jido.Messaging.Thread.t()]}
List threads for a room
@callback save_bridge_config(state(), Jido.Messaging.BridgeConfig.t()) :: {:ok, Jido.Messaging.BridgeConfig.t()} | {:error, term()}
Persist bridge config.
@callback save_ingress_subscription(state(), Jido.Messaging.IngressSubscription.t()) :: {:ok, Jido.Messaging.IngressSubscription.t()} | {:error, term()}
Persist normalized ingress subscription metadata.
@callback save_message(state(), Jido.Messaging.Message.t()) :: {:ok, Jido.Messaging.Message.t()} | {:error, term()}
Save a message
@callback save_onboarding(state(), onboarding_flow()) :: {:ok, onboarding_flow()} | {:error, term()}
Persist onboarding flow state.
@callback save_participant(state(), Jido.Chat.Participant.t()) :: {:ok, Jido.Chat.Participant.t()} | {:error, term()}
Save a participant (insert or update)
@callback save_room(state(), Jido.Chat.Room.t()) :: {:ok, Jido.Chat.Room.t()} | {:error, term()}
Save a room (insert or update)
@callback save_routing_policy(state(), Jido.Messaging.RoutingPolicy.t()) :: {:ok, Jido.Messaging.RoutingPolicy.t()} | {:error, term()}
Persist routing policy.
@callback save_thread(state(), Jido.Messaging.Thread.t()) :: {:ok, Jido.Messaging.Thread.t()} | {:error, term()}
Save a thread
@callback update_message_external_id(state(), message_id(), external_id()) :: {:ok, Jido.Messaging.Message.t()} | {:error, term()}
Update a message's external_id after successful channel delivery.
Used to record the external platform's message ID after sending.