cover/Elixir.Agent.Harness.html

1 defmodule Agent.Harness do
2 @moduledoc "Routes ask/tell messages to agents based on registration kind."
3 import Agent.Remote, only: [find: 1]
4 import Registry, only: [lookup: 2]
5 import String, only: [to_atom: 1]
6 import :global, only: [whereis_name: 1]
7 import Enum, only: [find_value: 3]
8 import Node, only: [list: 0]
9 import Utils.Normalize, only: [name: 1]
10
11 def dispatch(recipient, message, :ask) do
12 17 recipient |> locate() |> ask!(recipient, message)
13 end
14
15 def dispatch(recipient, message, :tell) do
16 31 recipient |> locate() |> tell!(recipient, message)
17 end
18
19 defp locate(recipient) do
20 48 entry(recipient) |> nearby(recipient)
21 end
22
23
:-(
defp nearby([], recipient), do: global(bare(recipient)) |> fallback(recipient)
24 48 defp nearby(found, _recipient), do: found
25
26 defp global(n) do
27
:-(
atom = to_atom(n)
28
:-(
result = whereis_name({atom |> to_string() |> name(), :puppet})
29
:-(
result |> local() |> remote(atom, result)
30 end
31
32
:-(
defp local(:undefined), do: :undefined
33
:-(
defp local(found), do: found |> wrap()
34
35
:-(
defp remote(:undefined, atom, _), do: list() |> search(atom)
36
:-(
defp remote(found, _, _), do: found
37
38
:-(
defp search(nodes, atom), do: find_value(nodes, :undefined, &fetch(&1, atom)) |> wrap()
39
40
:-(
defp fetch(node, atom) do
41
:-(
:erpc.call(node, :global, :whereis_name, [{atom |> to_string() |> name(), :puppet}], 5000)
42 catch
43
:-(
_, _ -> nil
44 end
45
46
:-(
defp fallback([], recipient), do: bare(recipient) |> find() |> wrap()
47
:-(
defp fallback(found, _), do: found
48
49
:-(
defp wrap(:undefined), do: []
50
:-(
defp wrap(pid), do: [{pid, %{kind: :puppet}}]
51
52 defp entry(recipient) do
53 48 clean = bare(recipient)
54 48 normalized = clean |> to_atom() |> Kernel.to_string() |> name()
55 48 lookup(ElitaRegistry, normalized)
56 end
57
58
:-(
defp bare("el." <> n), do: n
59 48 defp bare(n), do: n
60
61 48 defp impl(:native), do: Agent.Kind.Native
62
:-(
defp impl(:headless), do: Agent.Kind.Puppet
63
:-(
defp impl(:puppet), do: Agent.Kind.Puppet
64
65 defp ask!([{_pid, %{kind: kind}}] = entry, recipient, message) do
66 17 impl(kind).ask(entry, recipient, message)
67 end
68
69
:-(
defp ask!([], recipient, _message), do: "unknown: #{recipient}"
70
71 defp tell!([{_pid, %{kind: kind}}] = entry, recipient, message) do
72 31 impl(kind).forward(entry, recipient, message)
73 end
74
75
:-(
defp tell!([], recipient, _message), do: "unknown: #{recipient}"
76 end
Line Hits Source