Add support for spawning peers, and monitoring the processes

This commit is contained in:
bluepython508
2024-09-24 21:50:21 +01:00
parent 5e65fad33d
commit 23d3a97643
6 changed files with 94 additions and 17 deletions

View File

@@ -56,9 +56,8 @@ defmodule Frajtano.Agent do
end
@impl true
def handle_call({:add_peer, path}, _from, state) do
# TODO: deduplicate peers by socket path
case Peer.start(path) do
def handle_call({:add_peer, spec}, _from, state) do
case Peer.start(spec) do
{:ok, _} -> {:reply, :ok, state}
{:error, error} -> {:reply, {:error, error}, state}
end
@@ -73,7 +72,11 @@ defmodule Frajtano.Agent do
GenServer.call(__MODULE__, {:sign, request}, :infinity)
end
def add_peer(path) do
GenServer.call(__MODULE__, {:add_peer, path})
def assimilate(path) do
GenServer.call(__MODULE__, {:add_peer, {:socket, path}})
end
def spawn_peer(spec) do
GenServer.call(__MODULE__, {:add_peer, {:spawn, spec}})
end
end

View File

@@ -3,20 +3,59 @@ defmodule Frajtano.Peer do
require Logger
use GenServer, restart: :temporary
def start(path) do
DynamicSupervisor.start_child(Frajtano.PeerSupervisor, {__MODULE__, path})
defmodule Spawner do
use Supervisor, restart: :permanent
def start_link(spec) do
Supervisor.start_link(__MODULE__, spec, [])
end
@impl true
def init({executable, args}) do
Temp.track!()
path = Path.join(Temp.mkdir!(), "agent.sock")
children = [
Supervisor.child_spec({MuonTrap.Daemon, [executable, args ++ [path]]}, restart: :temporary, significant: true),
Supervisor.child_spec({Frajtano.Peer, {path, :spawned, {executable, args}}}, restart: :permanent)
]
Supervisor.init(children, strategy: :one_for_all, auto_shutdown: :any_significant)
end
end
def start_link(path) do
GenServer.start_link(__MODULE__, path, name: {:via, Registry, {Frajtano.Peers, path}})
def start({:socket, path}) do
DynamicSupervisor.start_child(Frajtano.PeerSupervisor, {__MODULE__, {path}})
end
def start({:spawn, spec}) do
DynamicSupervisor.start_child(Frajtano.PeerSupervisor, {Spawner, spec})
end
def start_link({path}) do
GenServer.start_link(__MODULE__, {path}, name: {:via, Registry, {Frajtano.Peers, path}})
end
def start_link({_, _, _} = spec) do
GenServer.start_link(__MODULE__, spec, name: {:via, Registry, {Frajtano.Peers, spec}})
end
@impl true
def init(path) do
def init({path}) do
{:ok, conn} = :gen_tcp.connect({:local, path}, 0, [:binary, active: :once])
{:ok, %{conn: conn, clients: :queue.new(), buffer: <<>>}}
end
@impl true
def init({path, :spawned, _}) do
if File.exists?(path) do
{:ok, conn} = :gen_tcp.connect({:local, path}, 0, [:binary, active: :once])
{:ok, %{conn: conn, clients: :queue.new(), buffer: <<>>}}
else
Process.sleep(100)
init({path, :spawned, nil})
end
end
def reply({client, ref}, msg) do
send(client, {ref, msg})
end