Created
November 14, 2024 22:47
-
-
Save cr0t/685184a621c18ba3617abdea7d07eb14 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule PortsEx.Basic do | |
use GenServer | |
require Logger | |
@command "./bin/long.rb" | |
def start_link(opts \\ []), | |
do: GenServer.start_link(__MODULE__, nil, opts) | |
def init(_) do | |
Port.open({:spawn, @command}, [:binary, :exit_status]) | |
{:ok, %{latest_output: nil, exit_status: nil}} | |
end | |
def handle_info({_port, {:data, line}}, state) do | |
latest_output = String.trim(line) | |
Logger.info("Latest output: #{latest_output}") | |
{:noreply, %{state | latest_output: latest_output}} | |
end | |
def handle_info({_port, {:exit_status, status}}, state) do | |
Logger.info("External exit: #{status}") | |
{:noreply, %{state | exit_status: status}} | |
end | |
def handle_info(msg, state) do | |
IO.inspect(msg, label: "Unexpected message") | |
{:noreply, state} | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
STDOUT.sync = true | |
puts "Starting up long process..." | |
TOTAL = 10 | |
TOTAL.times do |n| | |
sleep 1 | |
puts "Progress: step #{n + 1} of #{TOTAL}" | |
end | |
puts "Done" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule PortsEx.Monitored do | |
use GenServer | |
require Logger | |
@command "./bin/long.rb" | |
def start_link(opts \\ []), | |
do: GenServer.start_link(__MODULE__, nil, opts) | |
def init(_) do | |
port = Port.open({:spawn, @command}, [:binary, :exit_status]) | |
Port.monitor(port) | |
{:ok, %{port: port, latest_output: nil, exit_status: nil}} | |
end | |
def handle_info({_port, {:data, line}}, state) do | |
latest_output = String.trim(line) | |
Logger.info("Latest output: #{latest_output}") | |
{:noreply, %{state | latest_output: latest_output}} | |
end | |
def handle_info({_port, {:exit_status, status}}, state) do | |
Logger.info("External exit: #{status}") | |
{:noreply, %{state | exit_status: status}} | |
end | |
def handle_info({:DOWN, _ref, :port, port, :normal}, state) do | |
Logger.info("DOWN message from: #{inspect port}") | |
{:noreply, state} | |
end | |
def handle_info(msg, state) do | |
IO.inspect(msg, label: "Unexpected message") | |
{:noreply, state} | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule PortsEx.Trapped do | |
use GenServer | |
require Logger | |
@command "./bin/long.rb" | |
def start_link(opts \\ []), | |
do: GenServer.start_link(__MODULE__, nil, opts) | |
def init(_) do | |
Process.flag(:trap_exit, true) | |
port = Port.open({:spawn, @command}, [:binary, :exit_status]) | |
Port.monitor(port) | |
{:ok, %{port: port, latest_output: nil, exit_status: nil}} | |
end | |
def terminate(reason, state) do | |
Logger.info("TERMINATE: #{inspect reason}. Cleaning up...") | |
Logger.info("Final state: #{inspect state}") | |
port_info = Port.info(state.port) | |
os_pid = port_info[:os_pid] | |
Logger.warning("Orphaned OS process: #{os_pid}") | |
:normal | |
end | |
def handle_info({_port, {:data, line}}, state) do | |
latest_output = String.trim(line) | |
Logger.info("Latest output: #{latest_output}") | |
{:noreply, %{state | latest_output: latest_output}} | |
end | |
def handle_info({_port, {:exit_status, status}}, state) do | |
Logger.info("External exit: #{status}") | |
{:noreply, %{state | exit_status: status}} | |
end | |
def handle_info({:DOWN, _ref, :port, port, :normal}, state) do | |
Logger.info("DOWN message from: #{inspect port}") | |
{:noreply, state} | |
end | |
def handle_info({:EXIT, port, :normal}, state) do | |
Logger.info("EXIT message from: #{inspect port}") | |
{:noreply, state} | |
end | |
def handle_info(msg, state) do | |
IO.inspect(msg, label: "Unexpected message") | |
{:noreply, state} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment