DepMulti (dep_multi v0.1.2) View Source
DepMulti
is a data structure for performing dependant asynchronous
operations.
To demonstrate the problem, image you have three asynchronous tasks:
## [
Task.async(fn -> do_some_work() end),
Task.async(fn -> do_some_other_work() end),
Task.async(fn -> do_more_work() end),
] |> Enum.map(&Task.await/1)
This works until you have a dependency / ordering issue. Say do_more_work
must happen after do_some_work
. At that point, you'll need to name each
task and reference those names in other tasks that are dependant on them. If
those dependant task needs data from a previous task, you'll also want pass
those changes into the function.
The API to solve this issue is based on Ecto.Multi
(https://hexdocs.pm/ecto/Ecto.Multi.html),
and specifically run/3
and run/5
. The differences are:
- The tasks are executed asychronously
- the
run
methods take a list of dependencies and a timeout - the changes passed into the function only include direct or indirect dependencies
Example
iex> DepMulti.new() ...> |> DepMulti.run(:step1, [], fn -> ...> {:ok, 1} ...> end) ...> |> DepMulti.run(:step_2a, [dependencies: [:step_1], timeout: 5000], fn %{step_1: value} -> ...> {:ok, 2 + value} ...> end) ...> |> DepMulti.run(:step_2b, [dependencies: [:step_1]], Map, :fetch, [:step_1]) ...> |> DepMulti.execute() {:ok, %{step_1: 1, step_2a: 3, step_2b: 1}}
Link to this section Summary
Functions
Adds a function to run as part of the multi.
Adds a function to run as part of the multi.
Returns the list of operations stored in multi
.
Link to this section Types
Specs
changes() :: map()
Specs
dependencies() :: [name()]
Specs
name() :: any()
Specs
names() :: MapSet.t()
Specs
operations() :: [DepMulti.Operation.t()]
Specs
Specs
run_cmd() :: {:run, run()}
Specs
t() :: %DepMulti{names: names(), operations: operations()}
Link to this section Functions
Specs
Specs
new() :: t()
Returns an empty DepMulti
struct.
Example
iex> DepMulti.new() |> DepMulti.to_list()
[]
Specs
Adds a function to run as part of the multi.
The function should return either {:ok, value}
or {:error, value}
,
and receives the changes so far as the only argument.
NOTE: The changes will only include direct or indirect dependencies
Example
DepMulti.run(multi, :write, [:image], fn %{image: image} ->
with :ok <- File.write(image.name, image.contents) do
{:ok, nil}
end
end)
Specs
Adds a function to run as part of the multi.
Similar to run/4
, but allows to pass module name, function and arguments.
The function should return either {:ok, value}
or {:error, value}
, and
receives the rthe changes so far as the first argument (prepended to those
passed in the call to the function).
NOTE: The changes will only include direct or indirect dependencies
Specs
to_list(t()) :: operations()
Returns the list of operations stored in multi
.