Packages
phoenix
0.7.2
1.8.9
1.8.8
1.8.7
1.8.6
1.8.5
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.8.0-rc.4
1.8.0-rc.3
1.8.0-rc.2
1.8.0-rc.1
1.8.0-rc.0
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.7.0-rc.3
1.7.0-rc.2
1.7.0-rc.1
1.7.0-rc.0
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-rc.1
1.6.0-rc.0
1.5.15
1.5.14
1.5.13
1.5.12
1.5.11
1.5.10
1.5.9
1.5.8
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0-rc.0
1.4.18
1.4.17
1.4.16
1.4.15
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.3
1.4.0-rc.2
1.4.0-rc.1
1.4.0-rc.0
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.3.0-rc.3
1.3.0-rc.2
1.3.0-rc.1
1.3.0-rc.0
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc.1
1.2.0-rc.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.17.1
0.17.0
0.16.1
0.16.0
0.15.0
0.14.0
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.2
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.0
0.4.1
0.4.0
0.3.1
0.3.0
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.0
Productive. Reliable. Fast. A productive web framework that does not compromise speed or maintainability.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/phoenix/config.ex
defmodule Phoenix.Config.Supervisor do
@moduledoc false
use Supervisor
def start_link do
Supervisor.start_link(__MODULE__, [], name: __MODULE__)
end
def init([]) do
children = [
worker(Phoenix.Config, [], restart: :transient)
]
supervise children, strategy: :simple_one_for_one
end
end
defmodule Phoenix.Config do
# Handles Phoenix configuration.
#
# This module is private to Phoenix and should not be accessed
# directly. The Phoenix endpoint configuration can be accessed
# at runtime using the `config/2` function.
@moduledoc false
use GenServer
@doc """
Starts a supervised Phoenix configuration handler for runtime.
Data is accessed by the module via ETS.
"""
def start_supervised(otp_app, module, defaults) do
Supervisor.start_child(Phoenix.Config.Supervisor, [otp_app, module, defaults])
end
@doc """
Stops Phoenix configuration handler for the module.
"""
def stop(module) do
[__config__: pid] = :ets.lookup(module, :__config__)
GenServer.call(pid, :stop)
end
@doc """
Deep merges the given configuration.
"""
def merge(config1, config2) do
Keyword.merge(config1, config2, &merger/3)
end
@doc """
Caches a value in Phoenix configuration handler for the module.
Notice writes are not serialized to the server, we expect the
function that generates the cache to be idempotent.
"""
def cache(module, key, fun) do
case :ets.lookup(module, key) do
[{^key, val}] -> val
[] ->
val = fun.(module)
store(module, [{key, val}])
val
end
end
@doc """
Reads the configuration for module from the given otp app.
Useful to read a particular value at compilation time.
"""
def from_env(otp_app, module, defaults) do
config = Application.get_env(otp_app, module, [])
merge(defaults, config)
end
## Internal API
@doc """
Starts a linked Phoenix configuration handler.
"""
def start_link(otp_app, module, defaults) do
GenServer.start_link(__MODULE__, {otp_app, module, defaults})
end
@doc """
Stores the given keywords in the Phoenix configuration handler for the module.
"""
def store(module, pairs) do
pid = :ets.lookup_element(module, :__config__, 2)
GenServer.call(pid, {:store, pairs})
end
@doc """
Changes the configuration for the given module.
It receives a keyword list with changed config and another
with removed ones. The changed config are updated while the
removed ones stop the configuration server, effectively removing
the table.
"""
def config_change(module, changed, removed) do
pid = :ets.lookup_element(module, :__config__, 2)
GenServer.call(pid, {:config_change, changed, removed})
end
# Callbacks
def init({otp_app, module, defaults}) do
:ets.new(module, [:named_table, :protected, read_concurrency: true])
:ets.insert(module, [__config__: self()])
update(module, from_env(otp_app, module, defaults))
{:ok, {module, defaults}}
end
def handle_call({:store, config}, _from, {module, defaults}) do
:ets.insert(module, config)
{:reply, :ok, {module, defaults}}
end
def handle_call({:config_change, changed, removed}, _from, {module, defaults}) do
cond do
changed = changed[module] ->
update(module, merge(defaults, changed))
{:reply, :ok, {module, defaults}}
module in removed ->
stop(module, defaults)
true ->
{:reply, :ok, {module, defaults}}
end
end
def handle_call(:stop, _from, {module, defaults}) do
stop(module, defaults)
end
# Helpers
defp merger(_k, v1, v2) do
if Keyword.keyword?(v1) and Keyword.keyword?(v2) do
Keyword.merge(v1, v2, &merger/3)
else
v2
end
end
defp update(module, config) do
old_keys = keys(:ets.tab2list(module))
new_keys = [:__config__|keys(config)]
Enum.each old_keys -- new_keys, &:ets.delete(module, &1)
:ets.insert(module, config)
end
defp keys(data) do
Enum.map(data, &elem(&1, 0))
end
defp stop(module, defaults) do
:ets.delete(module)
{:stop, :normal, :ok, {module, defaults}}
end
end