Skip to content

Commit

Permalink
Add :callback to opts and use Supervisor.init/2
Browse files Browse the repository at this point in the history
* Adds a :callback to opts which takes a function capture
  or an MFA. The function is called when the :ets table
	is created and the supervisor is up.
* Uses Supervisor.init/2 to avoid deprecation messages
* Updates Elixir version to 1.5 which is when Supervisor.init/2
  was introduced
* Adds tests for the :callback option
  • Loading branch information
kipcole9 committed Jul 14, 2020
1 parent bcc1bc7 commit a738705
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 4 deletions.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Eternal is available on [Hex](https://hex.pm/). You can install the package via:

```elixir
def deps do
[{:eternal, "~> 1.2"}]
[{:eternal, "~> 1.3"}]
end
```

Expand Down Expand Up @@ -103,6 +103,17 @@ defmodule MyApplication.OneForAllSupervisor do
end
```

## Application callback

If your application would like to be informed when the supervisor is operation and the :ets table is created you may pass the option `:callback` to the `Eternal.start_link/3` and `Eternal.start/3` functions. The callback is a function specification of the form either `{Module, function, [args]}` or a function capture. For example:
```elixir
# The parameters pid and table are passed to the callback
iex> Eternal.start_link MyTable, [], callback: fn pid, table -> callback_fun(pid, table) end

# The parameters pid and table are pre-prended to args
iex> Eternal.start_link Eternal, [], callback: {MyModule, :callback_fun, []}, quiet: true
```

## Contributions

If you feel something can be improved, or have any questions about certain behaviours or pieces of implementation, please feel free to file an issue. Proposed changes should be taken to issues before any PRs to avoid wasting time on code which might not be merged upstream.
Expand Down
17 changes: 17 additions & 0 deletions lib/eternal.ex
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,24 @@ defmodule Eternal do
Priv.heir(table, pid2)
Priv.gift(table, pid1)

maybe_process_callback(opts[:callback], pid, table)
res
end
end

# Callback function when the :ets table
# is created and the supervisor process
# is up and running.
defp maybe_process_callback(nil, _pid, _table) do
nil
end

defp maybe_process_callback(fun, pid, table) when is_function(fun, 2) do
fun.(pid, table)
end

defp maybe_process_callback({module, function, args}, pid, table)
when is_mfa(module, function, args) do
:erlang.apply(module, function, [pid, table | args])
end
end
11 changes: 11 additions & 0 deletions lib/eternal/priv.ex
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,15 @@ defmodule Eternal.Priv do
is_list(unquote(opts))
end
end

@doc """
Determines if a 3-tuple is a {module, function, args}
"""
defmacro is_mfa(module, function, args) do
quote do
is_atom(unquote(module)) and
is_atom(unquote(function)) and
is_list(unquote(args))
end
end
end
2 changes: 1 addition & 1 deletion lib/eternal/supervisor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ defmodule Eternal.Supervisor do
worker(Eternal.Server, [{ table, flags, base }], id: Server.Two)
]

supervise(children, strategy: :one_for_one)
Supervisor.init(children, strategy: :one_for_one)
end

# Detects a potential name clash inside ETS. If we have a named table and the
Expand Down
4 changes: 2 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ defmodule Eternal.Mixfile do
},
maintainers: [ "Isaac Whitfield" ]
},
version: "1.2.1",
elixir: "~> 1.2",
version: "1.3.0",
elixir: "~> 1.5",
deps: deps(),
docs: [
extras: [ "README.md" ],
Expand Down
24 changes: 24 additions & 0 deletions test/eternal_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,30 @@ defmodule EternalTest do
assert(:ets.info(:table_with_options, :compressed) == true)
end

def callback_fun(_pid, table) do
require Logger

Logger.debug to_string(table)
end

test "starting with an MFA callback" do
msg = capture_log(fn ->
Eternal.start_link Eternal, [], callback: {__MODULE__, :callback_fun, []}, quiet: true
end)

assert msg =~ "Eternal"
end

test "starting with a function capture callback" do
require Logger

msg = capture_log(fn ->
Eternal.start_link Eternal, [], callback: fn pid, table -> callback_fun(pid, table) end, quiet: true
end)

assert msg =~ "Eternal"
end

test "starting a table with no link" do
spawn(fn ->
Eternal.start(:unlinked, [], [ quiet: true ])
Expand Down

0 comments on commit a738705

Please sign in to comment.