Packages

Flow based programming for elixir

Current section

Files

Jump to
virta lib registry.ex
Raw

lib/registry.ex

defmodule Virta.Registry do
use GenServer
alias Virta.Pool
alias Virta.InstanceSupervisor
# ------------------------------------------------------------------------------- Client API -----
@doc false
def child_spec(arg) do
super(arg)
end
@doc false
def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
@doc false
def get(name) do
GenServer.call(__MODULE__, { :get, name })
end
@doc """
Registers a graph and generates the workflow
```elixir
adder = Graph.new(type: :directed)
|> Graph.add_edge(
%Node{ module: Virta.Core.In, id: 0 },
%Node{ module: Virta.Math.Add, id: 1 },
label: %EdgeData{ from: :addend, to: :addend }
)
|> Graph.add_edge(
%Node{ module: Virta.Core.In, id: 0 },
%Node{ module: Virta.Math.Add, id: 1 },
label: %EdgeData{ from: :augend, to: :augend }
)
|> Graph.add_edge(
%Node{ module: Virta.Math.Add, id: 1 },
%Node{ module: Virta.Core.Out, id: 2 },
label: %EdgeData{ from: :sum, to: :output }
)
Virta.Registry.register("adder", adder)
```
"""
def register(name, graph) do
GenServer.cast(__MODULE__, { :register, name, graph })
end
@doc """
Unregister a graph and removes the workflow
```elixir
Virta.Registry.unregister("adder")
```
"""
def unregister(name) do
GenServer.cast(__MODULE__, { :unregister, name })
end
# ------------------------------------------------------------------------- Server Callbacks -----
@doc false
def init(_opts) do
{ :ok, %{} }
end
def handle_call({ :get, name }, _req, state) do
if Map.has_key?(state, name) do
{ :reply, Map.get(state, name), state }
else
{ :reply, nil, state }
end
end
def handle_cast({ :register, name, graph }, state) do
if Map.has_key?(state, name) do
{ :noreply, state }
else
{ :ok, pid } = DynamicSupervisor.start_child(InstanceSupervisor, { Pool, %{ name: name, graph: graph } })
{ :noreply, Map.put(state, name, pid) }
end
end
def handle_cast({ :unregister, name }, state) do
if Map.has_key?(state, name) do
DynamicSupervisor.terminate_child(InstanceSupervisor, Map.get(state, name))
{ :noreply, Map.delete(state, name) }
else
{ :noreply, state }
end
end
end