Merge branch 'develop' into feature/gen-magic
[akkoma] / lib / pleroma / gun / connection_pool / reclaimer.ex
1 defmodule Pleroma.Gun.ConnectionPool.Reclaimer do
2 use GenServer, restart: :temporary
3
4 @registry Pleroma.Gun.ConnectionPool
5
6 def start_monitor do
7 pid =
8 case :gen_server.start(__MODULE__, [], name: {:via, Registry, {@registry, "reclaimer"}}) do
9 {:ok, pid} ->
10 pid
11
12 {:error, {:already_registered, pid}} ->
13 pid
14 end
15
16 {pid, Process.monitor(pid)}
17 end
18
19 @impl true
20 def init(_) do
21 {:ok, nil, {:continue, :reclaim}}
22 end
23
24 @impl true
25 def handle_continue(:reclaim, _) do
26 max_connections = Pleroma.Config.get([:connections_pool, :max_connections])
27
28 reclaim_max =
29 [:connections_pool, :reclaim_multiplier]
30 |> Pleroma.Config.get()
31 |> Kernel.*(max_connections)
32 |> round
33 |> max(1)
34
35 :telemetry.execute([:pleroma, :connection_pool, :reclaim, :start], %{}, %{
36 max_connections: max_connections,
37 reclaim_max: reclaim_max
38 })
39
40 # :ets.fun2ms(
41 # fn {_, {worker_pid, {_, used_by, crf, last_reference}}} when used_by == [] ->
42 # {worker_pid, crf, last_reference} end)
43 unused_conns =
44 Registry.select(
45 @registry,
46 [
47 {{:_, :"$1", {:_, :"$2", :"$3", :"$4"}}, [{:==, :"$2", []}], [{{:"$1", :"$3", :"$4"}}]}
48 ]
49 )
50
51 case unused_conns do
52 [] ->
53 :telemetry.execute(
54 [:pleroma, :connection_pool, :reclaim, :stop],
55 %{reclaimed_count: 0},
56 %{
57 max_connections: max_connections
58 }
59 )
60
61 {:stop, :no_unused_conns, nil}
62
63 unused_conns ->
64 reclaimed =
65 unused_conns
66 |> Enum.sort(fn {_pid1, crf1, last_reference1}, {_pid2, crf2, last_reference2} ->
67 crf1 <= crf2 and last_reference1 <= last_reference2
68 end)
69 |> Enum.take(reclaim_max)
70
71 reclaimed
72 |> Enum.each(fn {pid, _, _} ->
73 DynamicSupervisor.terminate_child(Pleroma.Gun.ConnectionPool.WorkerSupervisor, pid)
74 end)
75
76 :telemetry.execute(
77 [:pleroma, :connection_pool, :reclaim, :stop],
78 %{reclaimed_count: Enum.count(reclaimed)},
79 %{max_connections: max_connections}
80 )
81
82 {:stop, :normal, nil}
83 end
84 end
85 end