I am working on two Elixir applications that interact via HTTP API calls.
The first application is bigger and for debugging/manual testing purposes I sometimes need to pilot HTTP responses of the second one. I created a controller in app2 that, after receiving a request, stops with an IO.gets
call and asks the user for what response to return. This works like a charm if app2 is started without a iex
session (mix run --no-halt
) but when started with iex -S mix
the user input is not received.
After some search on the web, I understand that the io of a given process is handled by its group leader and that there can be only one process handling standard input. In the iex
scenario the process handling stdin is the shell itself but the group leader of my controller is another process so the input is never received by the controller. (All correct?)
My current solution (simplified) is the following:
defmodule InteractiveController do
def handle_request(req) do
fix_group_leader()
resp = IO.gets("Select response\n")
resp
end
defp fix_group_leader, do: :user_drv |> Process.whereis() |> set_group_leader()
# we are in a iex session, we should get shell group leader and set it for current process
defp set_group_leader(pid) when is_pid(pid) do
iex_group_leader = pid |> Process.info() |> get_in([:dictionary, :current_group])
Process.group_leader(self(), iex_group_leader)
end
# no iex session
defp set_group_leader(_), do: :ok
end
This works but it seems a bit hacky…
Is there a better way to find the shell group leader?
Changing the group leader for the controller has some side effect?