Packages
phoenix
1.2.0
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 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 Phoenix configuration handler.
"""
def start_link(otp_app, module, defaults, opts \\ []) do
GenServer.start_link(__MODULE__, {otp_app, module, defaults}, opts)
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.
The given function needs to return a tuple with `:cache` if the
value should be cached or `:nocache` if the value should not be
cached because it can be consequently considered stale.
Notice writes are not serialized to the server, we expect the
function that generates the cache to be idempotent.
"""
@spec cache(module, term, (module -> {:cache | :nocache, term})) :: term
def cache(module, key, fun) do
case :ets.lookup(module, key) do
[{^key, :cache, val}] -> val
[] ->
case fun.(module) do
{:cache, val} ->
:ets.insert(module, {key, :cache, val})
val
{:nocache, val} ->
val
end
end
end
@doc """
Clears all cached entries in the endpoint.
"""
@spec clear_cache(module) :: :ok
def clear_cache(module) do
:ets.match_delete(module, {:_, :cache, :_})
:ok
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
@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, :public, read_concurrency: true])
:ets.insert(module, [__config__: self()])
update(module, from_env(otp_app, module, defaults))
{: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