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() @pub_sub EnVars.pub_sub() @writer_idle_ms EnVars.writer_idle_ms() @reader_idle_ms EnVars.reader_idle_ms() @store_description EnVars.store_description() @store_tags EnVars.store_tags() 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 Application.get_env(otp_app, :ex_esdb, []) 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(:otp_app, :ex_esdb) 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() 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() 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() 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(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() 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 pub_sub(otp_app) when is_atom(otp_app) do case sys_env(@pub_sub) do nil -> app_env(otp_app, :pub_sub, :ex_esdb_pubsub) pub_sub -> to_unique_atom(pub_sub) end end def pub_sub do context = get_context() if context != :ex_esdb do pub_sub(context) else case sys_env(@pub_sub) do nil -> app_env(:ex_esdb, :pub_sub, :ex_esdb_pubsub) pub_sub -> to_unique_atom(pub_sub) 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() 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() 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() 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() 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 defp to_unique_atom(candidate) do try do String.to_existing_atom(candidate) rescue _ -> String.to_atom(candidate) end end end