Current section
Files
Jump to
Current section
Files
lib/porter.ex
defmodule Porter do
use GenServer
alias Porter.Notifier
def start_link do
GenServer.start_link(__MODULE__, [Notifier.manager])
end
def init([pid]), do: {:ok, %{events_pid: pid}}
def run(cmd, callbacks) do
{:ok, pid} = start_link
GenServer.cast(pid, {:run, cmd, callbacks})
end
def handle_cast({:add_callback, callback}, state) do
Notifier.subscribe(state.events_pid, callback)
{:noreply, state}
end
def handle_cast({:run, cmd}, state) do
do_run(cmd, state.events_pid)
{:noreply, state}
end
def handle_cast({:run, cmd, callbacks}, state) do
for callback <- callbacks, do: Notifier.subscribe(state.events_pid, callback)
handle_cast({:run, cmd}, state)
end
def handle_cast(request, state) do
super(request, state)
end
defp do_run(cmd, pid) do
port = Port.open({:spawn, cmd}, [:stream, :binary, :exit_status])
loop(port, pid)
end
defp loop(port, pid) do
receive do
{port, data} -> handle_data(port, pid, data)
end
end
defp handle_data(port, pid, data) do
case data do
{:data, msg} ->
notify(pid, {:ok, {:data, msg}})
loop(port, pid)
{:exit_status, 0} ->
notify(pid, {:ok, {:exit_status, 0}})
{:exit_status, code} ->
notify(pid, {:error, {:exit_status, code}})
end
end
defp notify(pid, message), do: Notifier.notify(pid, message)
end