1 defmodule Pleroma.Gun.ConnectionPool.WorkerSupervisor do
2 @moduledoc "Supervisor for pool workers. Does not do anything except enforce max connection limit"
6 def start_link(opts) do
7 DynamicSupervisor.start_link(__MODULE__, opts, name: __MODULE__)
11 DynamicSupervisor.init(
12 strategy: :one_for_one,
13 max_children: Pleroma.Config.get([:connections_pool, :max_connections])
17 def start_worker(opts, retry \\ false) do
18 case DynamicSupervisor.start_child(__MODULE__, {Pleroma.Gun.ConnectionPool.Worker, opts}) do
19 {:error, :max_children} ->
20 if retry or free_pool() == :error do
21 :telemetry.execute([:pleroma, :connection_pool, :provision_failure], %{opts: opts})
24 start_worker(opts, true)
32 @registry Pleroma.Gun.ConnectionPool
33 @enforcer_key "enforcer"
35 case Registry.lookup(@registry, @enforcer_key) do
39 {:ok, _pid} = Registry.register(@registry, @enforcer_key, nil)
40 max_connections = Pleroma.Config.get([:connections_pool, :max_connections])
43 [:connections_pool, :reclaim_multiplier]
44 |> Pleroma.Config.get()
45 |> Kernel.*(max_connections)
49 :telemetry.execute([:pleroma, :connection_pool, :reclaim, :start], %{}, %{
50 max_connections: max_connections,
51 reclaim_max: reclaim_max
55 # fn {_, {worker_pid, {_, used_by, crf, last_reference}}} when used_by == [] ->
56 # {worker_pid, crf, last_reference} end)
61 {{:_, :"$1", {:_, :"$2", :"$3", :"$4"}}, [{:==, :"$2", []}],
62 [{{:"$1", :"$3", :"$4"}}]}
69 [:pleroma, :connection_pool, :reclaim, :stop],
70 %{reclaimed_count: 0},
72 max_connections: max_connections
76 exit(:no_unused_conns)
81 |> Enum.sort(fn {_pid1, crf1, last_reference1},
82 {_pid2, crf2, last_reference2} ->
83 crf1 <= crf2 and last_reference1 <= last_reference2
85 |> Enum.take(reclaim_max)
88 |> Enum.each(fn {pid, _, _} ->
89 DynamicSupervisor.terminate_child(__MODULE__, pid)
93 [:pleroma, :connection_pool, :reclaim, :stop],
94 %{reclaimed_count: Enum.count(reclaimed)},
95 %{max_connections: max_connections}
100 wait_for_enforcer_finish(pid)
103 wait_for_enforcer_finish(pid)
107 defp wait_for_enforcer_finish(pid) do
108 ref = Process.monitor(pid)
111 {:DOWN, ^ref, :process, ^pid, :no_unused_conns} ->
114 {:DOWN, ^ref, :process, ^pid, :normal} ->