Packages
ex_esdb
0.7.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.1
0.5.0
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
0.0.20
0.0.19
0.0.18
0.0.17
0.0.16
0.0.15
0.0.14-alpha
0.0.13-alpha
0.0.12-alpha
0.0.11-alpha
0.0.10-alpha
0.0.9-alpha
0.0.8-alpha
0.0.6-alpha
0.0.5-alpha
0.0.4-alpha
0.0.3-alpha
0.0.2-alfa
0.0.1-alfa
ExESDB is a reincarnation of rabbitmq/khepri, specialized for use as a BEAM-native event store.
Current section
Files
Jump to
Current section
Files
lib/options.ex
defmodule ExESDB.Options do
@moduledoc """
This module contains the options helper functions for ExESDB
Modified to support umbrella configuration patterns where configurations
are stored under individual app names instead of the global :ex_esdb key.
"""
alias ExESDB.EnVars, as: EnVars
@data_dir EnVars.data_dir()
@store_id EnVars.store_id()
@timeout EnVars.timeout()
@db_type EnVars.db_type()
@writer_idle_ms EnVars.writer_idle_ms()
@reader_idle_ms EnVars.reader_idle_ms()
@store_description EnVars.store_description()
@store_tags EnVars.store_tags()
@persistence_interval EnVars.persistence_interval()
@persistence_enabled EnVars.persistence_enabled()
def sys_env(key), do: System.get_env(key)
# Support for umbrella configuration patterns
def app_env(otp_app) when is_atom(otp_app) do
config = Application.get_env(otp_app, :ex_esdb, [])
enhanced_config = Keyword.put(config, :otp_app, otp_app)
enhanced_config
end
# Support for umbrella configuration patterns with defaults
def app_env(otp_app, key, default) when is_atom(otp_app) and is_atom(key) do
Keyword.get(app_env(otp_app), key, default)
end
def topologies, do: Application.get_env(:libcluster, :topologies)
# Configuration context support for umbrella apps
def set_context(otp_app) when is_atom(otp_app) do
Process.put(:ex_esdb_otp_app, otp_app)
end
def get_context do
Process.get(:ex_esdb_otp_app, :ex_esdb)
end
# Enhanced version that tries harder to find the context
def get_context_or_discover do
case get_context() do
:ex_esdb ->
# Try to discover from application environment or loaded apps
discover_current_app() || :ex_esdb
context ->
context
end
end
# Helper to discover current app when context is not set
# The simple approach: find which application has ExESDB configuration
defp discover_current_app do
# First try loaded applications
loaded_app = Application.loaded_applications()
|> Enum.find_value(fn {app, _desc, _vsn} ->
case Application.get_env(app, :ex_esdb) do
nil -> nil
_config -> app
end
end)
if loaded_app do
loaded_app
else
# If no loaded app has config, use the built-in Erlang application environment mechanism
# This is the "out-of-the-box" approach: check all apps that have our key set
:application.info()
|> Keyword.get(:loaded, [])
|> Enum.find_value(fn app ->
case :application.get_env(app, :ex_esdb) do
{:ok, _config} -> app
:undefined -> nil
end
end)
end
end
def with_context(otp_app, fun) when is_atom(otp_app) and is_function(fun, 0) do
previous_context = Process.get(:ex_esdb_otp_app)
Process.put(:ex_esdb_otp_app, otp_app)
try do
fun.()
after
if previous_context do
Process.put(:ex_esdb_otp_app, previous_context)
else
Process.delete(:ex_esdb_otp_app)
end
end
end
# Umbrella-aware versions of configuration functions
def data_dir(otp_app) when is_atom(otp_app) do
case sys_env(@data_dir) do
nil -> app_env(otp_app, :data_dir, "/data")
data_dir -> data_dir
end
end
def data_dir do
context = get_context_or_discover()
if context != :ex_esdb do
data_dir(context)
else
case sys_env(@data_dir) do
nil -> app_env(:ex_esdb, :data_dir, "/data")
data_dir -> data_dir
end
end
end
def store_id(otp_app) when is_atom(otp_app) do
case sys_env(@store_id) do
nil -> app_env(otp_app, :store_id, :undefined)
store_id -> to_unique_atom(store_id)
end
end
def store_id do
context = get_context_or_discover()
if context != :ex_esdb do
store_id(context)
else
case sys_env(@store_id) do
nil -> app_env(:ex_esdb, :store_id, :undefined)
store_id -> to_unique_atom(store_id)
end
end
end
def timeout(otp_app) when is_atom(otp_app) do
case sys_env(@timeout) do
nil -> app_env(otp_app, :timeout, 10_000)
timeout -> String.to_integer(timeout)
end
end
def timeout do
context = get_context_or_discover()
if context != :ex_esdb do
timeout(context)
else
case sys_env(@timeout) do
nil -> app_env(:ex_esdb, :timeout, 10_000)
timeout -> String.to_integer(timeout)
end
end
end
def db_type(:ex_esdb), do: db_type()
def db_type(otp_app) when is_atom(otp_app) do
case sys_env(@db_type) do
nil -> app_env(otp_app, :db_type, :single)
db_type -> String.to_atom(db_type)
end
end
def db_type do
context = get_context_or_discover()
if context != :ex_esdb do
db_type(context)
else
case sys_env(@db_type) do
nil -> app_env(:ex_esdb, :db_type, :single)
db_type -> String.to_atom(db_type)
end
end
end
def reader_idle_ms(otp_app) when is_atom(otp_app) do
case sys_env(@reader_idle_ms) do
nil -> app_env(otp_app, :reader_idle_ms, 10_000)
reader_idle_ms -> String.to_integer(reader_idle_ms)
end
end
def reader_idle_ms do
context = get_context_or_discover()
if context != :ex_esdb do
reader_idle_ms(context)
else
case sys_env(@reader_idle_ms) do
nil -> app_env(:ex_esdb, :reader_idle_ms, 10_000)
reader_idle_ms -> String.to_integer(reader_idle_ms)
end
end
end
def writer_idle_ms(otp_app) when is_atom(otp_app) do
case sys_env(@writer_idle_ms) do
nil -> app_env(otp_app, :writer_idle_ms, 10_000)
writer_idle_ms -> String.to_integer(writer_idle_ms)
end
end
def writer_idle_ms do
context = get_context_or_discover()
if context != :ex_esdb do
writer_idle_ms(context)
else
case sys_env(@writer_idle_ms) do
nil -> app_env(:ex_esdb, :writer_idle_ms, 10_000)
writer_idle_ms -> String.to_integer(writer_idle_ms)
end
end
end
def store_description(otp_app) when is_atom(otp_app) do
case sys_env(@store_description) do
nil -> app_env(otp_app, :store_description, "undefined!")
store_description -> store_description
end
end
def store_description do
context = get_context_or_discover()
if context != :ex_esdb do
store_description(context)
else
case sys_env(@store_description) do
nil -> app_env(:ex_esdb, :store_description, "undefined!")
store_description -> store_description
end
end
end
def store_tags(otp_app) when is_atom(otp_app) do
case sys_env(@store_tags) do
nil ->
app_env(otp_app, :store_tags, [])
tags_string ->
tags_string
|> String.split(",")
|> Enum.map(&String.trim/1)
|> Enum.reject(&(&1 == ""))
end
end
def store_tags do
context = get_context_or_discover()
if context != :ex_esdb do
store_tags(context)
else
case sys_env(@store_tags) do
nil ->
app_env(:ex_esdb, :store_tags, [])
tags_string ->
tags_string
|> String.split(",")
|> Enum.map(&String.trim/1)
|> Enum.reject(&(&1 == ""))
end
end
end
def persistence_interval(otp_app) when is_atom(otp_app) do
case sys_env(@persistence_interval) do
nil -> app_env(otp_app, :persistence_interval, 5_000)
interval -> String.to_integer(interval)
end
end
def persistence_interval do
context = get_context_or_discover()
if context != :ex_esdb do
persistence_interval(context)
else
case sys_env(@persistence_interval) do
nil -> app_env(:ex_esdb, :persistence_interval, 5_000)
interval -> String.to_integer(interval)
end
end
end
def persistence_enabled(otp_app) when is_atom(otp_app) do
case sys_env(@persistence_enabled) do
nil -> app_env(otp_app, :persistence_enabled, true)
enabled -> String.to_atom(enabled)
end
end
def persistence_enabled do
context = get_context_or_discover()
if context != :ex_esdb do
persistence_enabled(context)
else
case sys_env(@persistence_enabled) do
nil -> app_env(:ex_esdb, :persistence_enabled, true)
enabled -> String.to_atom(enabled)
end
end
end
defp to_unique_atom(candidate) do
try do
String.to_existing_atom(candidate)
rescue
_ -> String.to_atom(candidate)
end
end
end