defmodule EventodbKit do @moduledoc """ Production-ready Elixir SDK for EventoDB with resilience patterns. EventodbKit provides: - Outbox pattern for reliable event publishing - Consumer position tracking - Idempotency for producers and consumers - Singleton workers via Chosen - Built on top of EventodbEx """ alias EventodbKit.Client alias EventodbKit.Outbox # Write operations (to outbox) @doc """ Writes a message to the outbox for eventual delivery to EventoDB. ## Examples {:ok, outbox_id, kit} = EventodbKit.stream_write( kit, "account-123", %{type: "Deposited", data: %{amount: 100}} ) """ def stream_write(%Client{} = kit, stream, message, opts \\ []) do case Outbox.write(kit.repo, kit.namespace, stream, message, opts) do {:ok, outbox_id} -> {:ok, outbox_id, kit} {:error, reason} -> {:error, reason} end end @doc """ Writes multiple messages to the outbox. """ def stream_write_batch(%Client{} = kit, messages, opts \\ []) do case Outbox.write_batch(kit.repo, kit.namespace, messages, opts) do {:ok, outbox_ids} -> {:ok, outbox_ids, kit} {:error, reason} -> {:error, reason} end end # Read operations (delegate to EventodbEx) @doc """ Reads all messages from a stream. """ def stream_get(%Client{} = kit, stream, opts \\ %{}) do case EventodbEx.stream_get(kit.eventodb_client, stream, opts) do {:ok, messages, client} -> {:ok, messages, %{kit | eventodb_client: client}} {:error, reason} -> {:error, reason} end end @doc """ Gets the last message from a stream. """ def stream_last(%Client{} = kit, stream, opts \\ %{}) do case EventodbEx.stream_last(kit.eventodb_client, stream, opts) do {:ok, message, client} -> {:ok, message, %{kit | eventodb_client: client}} {:error, reason} -> {:error, reason} end end @doc """ Gets the current version of a stream. """ def stream_version(%Client{} = kit, stream) do case EventodbEx.stream_version(kit.eventodb_client, stream) do {:ok, version, client} -> {:ok, version, %{kit | eventodb_client: client}} {:error, reason} -> {:error, reason} end end @doc """ Reads messages from a category. """ def category_get(%Client{} = kit, category, opts \\ %{}) do case EventodbEx.category_get(kit.eventodb_client, category, opts) do {:ok, messages, client} -> {:ok, messages, %{kit | eventodb_client: client}} {:error, reason} -> {:error, reason} end end # Namespace operations (delegate to EventodbEx) @doc """ Creates a new namespace. """ def namespace_create(%Client{} = kit, namespace_id, opts \\ %{}) do case EventodbEx.namespace_create(kit.eventodb_client, namespace_id, opts) do {:ok, result, client} -> {:ok, result, %{kit | eventodb_client: client}} {:error, reason} -> {:error, reason} end end @doc """ Deletes a namespace. """ def namespace_delete(%Client{} = kit, namespace_id) do case EventodbEx.namespace_delete(kit.eventodb_client, namespace_id) do {:ok, result, client} -> {:ok, result, %{kit | eventodb_client: client}} {:error, reason} -> {:error, reason} end end @doc """ Lists all namespaces. """ def namespace_list(%Client{} = kit) do case EventodbEx.namespace_list(kit.eventodb_client) do {:ok, list, client} -> {:ok, list, %{kit | eventodb_client: client}} {:error, reason} -> {:error, reason} end end @doc """ Gets namespace information. """ def namespace_info(%Client{} = kit, namespace_id) do case EventodbEx.namespace_info(kit.eventodb_client, namespace_id) do {:ok, info, client} -> {:ok, info, %{kit | eventodb_client: client}} {:error, reason} -> {:error, reason} end end @doc """ Lists streams in the current namespace with optional prefix filtering and pagination. ## Options * `:prefix` - Filter streams whose name starts with this string * `:limit` - Max streams to return (default: 100, max: 1000) * `:cursor` - Pagination cursor — return streams after this name (exclusive) See `EventodbEx.namespace_streams/2` for full details. """ def namespace_streams(%Client{} = kit, opts \\ %{}) do case EventodbEx.namespace_streams(kit.eventodb_client, opts) do {:ok, streams, client} -> {:ok, streams, %{kit | eventodb_client: client}} {:error, reason} -> {:error, reason} end end @doc """ Lists distinct categories in the current namespace with stream and message counts. Takes no options. Returns all categories sorted lexicographically. Each entry has `:category`, `:stream_count`, and `:message_count`. See `EventodbEx.namespace_categories/1` for full details. """ def namespace_categories(%Client{} = kit) do case EventodbEx.namespace_categories(kit.eventodb_client) do {:ok, categories, client} -> {:ok, categories, %{kit | eventodb_client: client}} {:error, reason} -> {:error, reason} end end end