logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

reclaimer.ex (2403B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Gun.ConnectionPool.Reclaimer do
  5. use GenServer, restart: :temporary
  6. defp registry, do: Pleroma.Gun.ConnectionPool
  7. def start_monitor do
  8. pid =
  9. case GenServer.start_link(__MODULE__, [], name: {:via, Registry, {registry(), "reclaimer"}}) do
  10. {:ok, pid} ->
  11. pid
  12. {:error, {:already_registered, pid}} ->
  13. pid
  14. end
  15. {pid, Process.monitor(pid)}
  16. end
  17. @impl true
  18. def init(_) do
  19. {:ok, nil, {:continue, :reclaim}}
  20. end
  21. @impl true
  22. def handle_continue(:reclaim, _) do
  23. max_connections = Pleroma.Config.get([:connections_pool, :max_connections])
  24. reclaim_max =
  25. [:connections_pool, :reclaim_multiplier]
  26. |> Pleroma.Config.get()
  27. |> Kernel.*(max_connections)
  28. |> round
  29. |> max(1)
  30. :telemetry.execute([:pleroma, :connection_pool, :reclaim, :start], %{}, %{
  31. max_connections: max_connections,
  32. reclaim_max: reclaim_max
  33. })
  34. # :ets.fun2ms(
  35. # fn {_, {worker_pid, {_, used_by, crf, last_reference}}} when used_by == [] ->
  36. # {worker_pid, crf, last_reference} end)
  37. unused_conns =
  38. Registry.select(
  39. registry(),
  40. [
  41. {{:_, :"$1", {:_, :"$2", :"$3", :"$4"}}, [{:==, :"$2", []}], [{{:"$1", :"$3", :"$4"}}]}
  42. ]
  43. )
  44. case unused_conns do
  45. [] ->
  46. :telemetry.execute(
  47. [:pleroma, :connection_pool, :reclaim, :stop],
  48. %{reclaimed_count: 0},
  49. %{
  50. max_connections: max_connections
  51. }
  52. )
  53. {:stop, :no_unused_conns, nil}
  54. unused_conns ->
  55. reclaimed =
  56. unused_conns
  57. |> Enum.sort(fn {_pid1, crf1, last_reference1}, {_pid2, crf2, last_reference2} ->
  58. crf1 <= crf2 and last_reference1 <= last_reference2
  59. end)
  60. |> Enum.take(reclaim_max)
  61. reclaimed
  62. |> Enum.each(fn {pid, _, _} ->
  63. DynamicSupervisor.terminate_child(Pleroma.Gun.ConnectionPool.WorkerSupervisor, pid)
  64. end)
  65. :telemetry.execute(
  66. [:pleroma, :connection_pool, :reclaim, :stop],
  67. %{reclaimed_count: Enum.count(reclaimed)},
  68. %{max_connections: max_connections}
  69. )
  70. {:stop, :normal, nil}
  71. end
  72. end
  73. end