Raxol.Gateway.Adapter.Email.ThreadStore (RaxolGateway v0.2.0)

Copy Markdown View Source

Remembers the last inbound message per email conversation so an outbound reply can thread against it.

Raxol.Gateway.Adapter.Email.send_message/3 cannot learn the inbound Message-ID from its arguments -- the Raxol.Gateway.Adapter contract is frozen at (conn, route, rendered). This store closes that gap: the inbound feed's wiring records each normalized message here (keyed by the conversation address), and the adapter reads it back at send time through the conn's :thread_lookup function, which thread_lookup_fn/1 builds.

The store is a small in-memory cap map (one entry per conversation address, most-recently-seen wins), bounded by :max_entries (default 10_000) with oldest-recorded eviction. It holds only mail metadata (Message-ID, references, subject) -- never message bodies.

Wiring

{:ok, store} = ThreadStore.start_link(name: MyThreads)

on_message = fn raw ->
  case Email.normalize_event(raw) do
    {:ok, route, event} ->
      ThreadStore.record_event(store, route, event)
      SessionRouter.route(router, route, event)

    :ignore ->
      :ok
  end
end

{:ok, conn} =
  Email.connect(
    relay: relay,
    from: from,
    thread_lookup: ThreadStore.thread_lookup_fn(store)
  )

Summary

Functions

Returns a specification to start this module under a supervisor.

The recorded inbound message for key, or :none.

Record the inbound message meta for a conversation key.

Record the inbound message from a normalized {route, event}.

A (route -> meta | nil) function for Email.connect's :thread_lookup.

Types

meta()

@type meta() :: %{optional(atom()) => term()}

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

handle_manager_cast(msg, state)

Callback implementation for Raxol.Core.Behaviours.BaseManager.handle_manager_cast/2.

handle_manager_info(msg, state)

Callback implementation for Raxol.Core.Behaviours.BaseManager.handle_manager_info/2.

lookup(server, key)

@spec lookup(GenServer.server(), String.t()) :: {:ok, meta()} | :none

The recorded inbound message for key, or :none.

record(server, key, meta)

@spec record(GenServer.server(), String.t(), meta()) :: :ok

Record the inbound message meta for a conversation key.

record_event(server, arg2, arg3)

@spec record_event(GenServer.server(), Raxol.Gateway.Route.t() | map(), map()) :: :ok

Record the inbound message from a normalized {route, event}.

A no-op unless the event carries the :email metadata normalize_event/1 produces, so it is safe to call on every routed event.

start_link(init_opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

thread_lookup_fn(server)

@spec thread_lookup_fn(GenServer.server()) :: (map() -> meta() | nil)

A (route -> meta | nil) function for Email.connect's :thread_lookup.

Resolves the reply-threading metadata for a route by its chat_id (the conversation address); nil when nothing has been recorded yet.