Wormhole captures anything that is emitted out of the callback
(return value or error reason) and transfers it to the calling process
in the form {:ok, state} or {:error, reason}.
Wormhole invokes callback in separate process and
waits for message from callback process containing callback return value
if finished successfully or
error reason if callback process failed for any reason.
If callback execution is not finished within specified timeout,
callback process is killed and error returned.
Default timeout value is specified in @timeout_ms.
User can specify timeout_ms in options keyword list.
By default there is no retry, but user can specify
retry_count and backoff_ms in options.
Default back-off time value is specified in @backoff_ms.
Note: retry_count specifies maximum number of times callback can be invoked.
More accurate name would be try_count but I think it would bring
more confusion than clarity, hence the name remains.
By default exceptions in callback-process are handled so that
supervisor does not generate CRUSH REPORT (when released - Exrm/Distillery).
This behavior can be overridden by setting crush_report to true.
Note:
- Crush report is not generated in Elixir by default.
- Letting exceptions propagate might be useful for some other applications too (e.g sentry client).
Add to the list of dependencies:
def deps do
[
{:wormhole, github: "renderedtext/wormhole"}
]
endAdd to the list of applications:
def application do
[applications: [:wormhole]]
endUnnamed function:
iex> Wormhole.capture(fn-> :a end)
{:ok, :a}Named function without arguments:
iex> Wormhole.capture(&Process.list/0)
{:ok, [#PID<0.0.0>, #PID<0.3.0>, #PID<0.6.0>, #PID<0.7.0>, ...]}Named function with arguments:
iex> Wormhole.capture(Enum, :count, [[1,2,3]])
{:ok, 3}Both versions with timeout explicitly set to 2 seconds:
iex> Wormhole.capture(&Process.list/0, timeout_ms: 2_000)
{:ok, [#PID<0.0.0>, #PID<0.3.0>, #PID<0.6.0>, #PID<0.7.0>, ...]}
iex> Wormhole.capture(Enum, :count, [[1,2,3]], timeout_ms: 2_000)
{:ok, 3}defmodule Test do
def f do
raise "Hello"
end
end
iex> Wormhole.capture(&Test.f/0)
{:error,
{%RuntimeError{message: "Hello"},
[{Test, :f, 0, [file: 'iex', line: 23]},
{Wormhole, :"-send_return_value/1-fun-0-", 2,
[file: 'lib/wormhole.ex', line: 75]}]}}
iex> Wormhole.capture(fn-> throw :foo end)
{:error,
{{:nocatch, :foo},
[{Wormhole, :"-send_return_value/1-fun-0-", 2,
[file: 'lib/wormhole.ex', line: 75]}]}}
iex> Wormhole.capture(fn-> exit :foo end)
{:error, :foo}iex> Wormhole.capture(&foo/0, [timeout_ms: 2_000, retry_count: 3, backoff_ms: 300])def ... do
...
(&some_function/0) |> Wormhole.capture |> some_function_response_handler
...
end
def some_function_response_handler({:ok, response}) do
...
end
def some_function_response_handler({:error, error}) do
...
end