Current section
Files
Jump to
Current section
Files
lib/child_spec_compat.ex
defmodule ChildSpecCompat do
@moduledoc """
Provides Elixir compatibility for versions prior to v1.5.
The new `Supervisor.child_spec/2` functions are recommended but only
exist after Elixir v1.5. This is not easy to migrate to inside library
modules which support multiple Elixir versions, and so this module
aims to make this transition easier. This works by transforming the
new form back to the old style to allow migration to the new patterns.
"""
@doc """
Builds and overrides a child specification.
This will pass straight through to the `Supervisor` child specification
functions on Elixir v1.5, and wrap into an older record format on older
versions.
You can use this when your code targets Elixir runtimes both prior to
and after Elixir v1.5 (e.g. libraries and common modules).
"""
defmacro child_spec(module_or_map, overrides \\ []) do
has_child_spec =
:functions
|> Supervisor.__info__()
|> Keyword.keys()
|> Enum.member?(:child_spec)
case has_child_spec do
true ->
quote bind_quoted: binding() do
Supervisor.child_spec(module_or_map, overrides)
end
false ->
quote bind_quoted: binding() do
# specification shimming
modified_spec =
Enum.reduce(
# iteratee
overrides,
# generate initial child specification
case module_or_map do
# specification is provided
map when is_map(map) ->
map
# only module is provided
mod when is_atom(mod) ->
mod.child_spec([])
# module and arguments are provded
{mod, args} when is_atom(mod) ->
mod.child_spec(args)
end,
# apply overrides to spec
fn {field, value}, spec ->
Map.put(spec, field, value)
end
)
# :id and :start are required
id = Map.fetch!(modified_spec, :id)
start = Map.fetch!(modified_spec, :start)
# :type and :restart allow default values
type = Map.get(modified_spec, :type, :worker)
restart = Map.get(modified_spec, :restart, :permanent)
# the shutdown needs to know the child :type value
shutdown = Map.get_lazy(modified_spec, :shutdown, fn ->
case type do
:supervisor -> :infinity
:worker -> 5000
end
end)
# restructure all into the old tuple format
{ id, start, restart, shutdown, type, [id] }
end
end
end
end