thomas.fortes
Best way to get a pid for a supervisors child
I’m deploying an app at fly.io that can shut down when idle, this post from Chris McCord shows how to do it, but in the app I’m using bandit and thousand island, not cowboy and ranch, so I asked @mtrudel if thousand island supported introspection and he implemented a way to get the connection pids from a server, which was awesomely nice of him.
Anyway, my solution uses the exact same structure as the Chris McCord one but replacing the use of ranch with Bandit and Thousand Island, the problem is that I don’t see anything wrong and it works perfectly, but maybe some of you know a more elegant way to fetch the pid needed, here’s the code:
defp shutdown_when_inactive(every_ms) do
Process.sleep(every_ms)
pid =
Supervisor.which_children(AppWeb.Endpoint)
|> Enum.find(fn c ->
case c do
{{AppWeb.Endpoint, :http}, _pid, :worker, [Bandit]} -> true
_ -> false
end
end)
|> elem(1)
{:ok, connections} = ThousandIsland.connection_pids(pid)
if connections == [] do
System.stop(0)
else
shutdown_when_inactive(every_ms)
end
end
Thanks
Most Liked
mtrudel
Great to hear you got this working!
As you’ve figured out, once you get a handle on the root Bandit process (which is actually just a Thousand Island server process), you can get the list of current connection processes for it via the ThousandIsland.connection_pids/1 function added in Thousand Island 0.5.17. That part is pretty straightforward.
This leaves the problem of how to get the Bandit/Thousand Island pid from an Endpoint process (accessible via id as the Endpoint’s module name). Pulling out specific children of a supervisor (by id or otherwise) is always as awkward as you’ve done here; there’s not really an easier way. There’s a million ways to golf this sort of thing down to something more elegant but I’ve never really seen an approach I like; curious if anyone else has a better approach. FWIW I use a pattern more or less like you do here within Thousand Island.
fceruti
Cool, thanks!
For future reference, here’s the snippet using everything I learned today ![]()
defp shutdown_when_inactive(every_ms) do
Process.sleep(every_ms)
{_, pid, _, _} =
AppWeb.Endpoint
|> Supervisor.which_children()
|> Enum.find(&Kernel.match?({{AppWeb.Endpoint, :http}, _pid, _type, [Bandit]}, &1))
{:ok, connections} = ThousandIsland.connection_pids(pid)
if connections == [] do
System.stop(0)
else
shutdown_when_inactive(every_ms)
end
end
thomas.fortes
Yeah, your approach is more elegant than mine, similar idea, cleaner execution, still wondering if someone has a different approach.
Thanks again
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









