Session key derivation for conversation scoping.
Provides a canonical way to derive a unique session identifier from a message context. This enables applications to scope conversations by channel, bridge, room, and optionally thread.
The session key is a tuple that can be used as a process registry key, ETS key, or any other lookup mechanism that requires a unique conversation identifier.
Usage
# Derive session key from message context
key = SessionKey.from_context(msg_context)
#=> {:telegram, "bot_123", "chat_456", nil}
# With thread scoping
key = SessionKey.from_context(threaded_msg_context)
#=> {:telegram, "bot_123", "chat_456", "thread_789"}
# Convert to string for string-keyed stores
SessionKey.to_string(key)
#=> "telegram:bot_123:chat_456"
Summary
Functions
Derives a session key from a MsgContext.
Parses a string representation back into a session key tuple.
Checks if two session keys belong to the same conversation scope.
Converts a session key to a string representation.
Types
Functions
@spec from_context(Jido.Messaging.MsgContext.t()) :: t()
Derives a session key from a MsgContext.
Uses room_id if resolved (internal UUID), otherwise falls back to external_room_id.
Thread scoping uses resolved thread_id when present and otherwise falls back to
external_thread_id.
Examples
iex> ctx = %MsgContext{channel_type: :telegram, bridge_id: "bot_1", external_room_id: "123", room_id: nil, thread_id: nil}
iex> SessionKey.from_context(ctx)
{:telegram, "bot_1", "123", nil}
iex> ctx = %MsgContext{channel_type: :discord, bridge_id: "guild_1", external_room_id: "ch_1", room_id: "uuid-123", thread_id: "thread_456"}
iex> SessionKey.from_context(ctx)
{:discord, "guild_1", "uuid-123", "thread_456"}
Parses a string representation back into a session key tuple.
Returns {:ok, key} on success, {:error, :invalid_format} on failure.
Examples
iex> SessionKey.parse("telegram:bot_1:chat_123")
{:ok, {:telegram, "bot_1", "chat_123", nil}}
iex> SessionKey.parse("discord:guild_1:ch_1:thread_456")
{:ok, {:discord, "guild_1", "ch_1", "thread_456"}}
iex> SessionKey.parse("invalid")
{:error, :invalid_format}
Checks if two session keys belong to the same conversation scope.
Two keys match if channel_type, bridge_id, and room_id are equal. Thread IDs are not compared (both threaded and non-threaded messages in the same room match).
Examples
iex> key1 = {:telegram, "bot_1", "chat_123", nil}
iex> key2 = {:telegram, "bot_1", "chat_123", "thread_456"}
iex> SessionKey.same_room?(key1, key2)
true
iex> key1 = {:telegram, "bot_1", "chat_123", nil}
iex> key2 = {:telegram, "bot_1", "chat_456", nil}
iex> SessionKey.same_room?(key1, key2)
false
Converts a session key to a string representation.
Useful for string-keyed stores like Redis or as a log identifier. Thread ID is omitted if nil.
Examples
iex> SessionKey.to_string({:telegram, "bot_1", "chat_123", nil})
"telegram:bot_1:chat_123"
iex> SessionKey.to_string({:discord, "guild_1", "ch_1", "thread_456"})
"discord:guild_1:ch_1:thread_456"