89 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Elixir
		
	
	
	
	
	
			
		
		
	
	
			89 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Elixir
		
	
	
	
	
	
# Pleroma: A lightweight social networking server
 | 
						|
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
 | 
						|
# SPDX-License-Identifier: AGPL-3.0-only
 | 
						|
 | 
						|
defmodule Pleroma.Gun.ConnectionPool.Reclaimer do
 | 
						|
  use GenServer, restart: :temporary
 | 
						|
 | 
						|
  defp registry, do: Pleroma.Gun.ConnectionPool
 | 
						|
 | 
						|
  def start_monitor do
 | 
						|
    pid =
 | 
						|
      case :gen_server.start(__MODULE__, [], name: {:via, Registry, {registry(), "reclaimer"}}) do
 | 
						|
        {:ok, pid} ->
 | 
						|
          pid
 | 
						|
 | 
						|
        {:error, {:already_registered, pid}} ->
 | 
						|
          pid
 | 
						|
      end
 | 
						|
 | 
						|
    {pid, Process.monitor(pid)}
 | 
						|
  end
 | 
						|
 | 
						|
  @impl true
 | 
						|
  def init(_) do
 | 
						|
    {:ok, nil, {:continue, :reclaim}}
 | 
						|
  end
 | 
						|
 | 
						|
  @impl true
 | 
						|
  def handle_continue(:reclaim, _) do
 | 
						|
    max_connections = Pleroma.Config.get([:connections_pool, :max_connections])
 | 
						|
 | 
						|
    reclaim_max =
 | 
						|
      [:connections_pool, :reclaim_multiplier]
 | 
						|
      |> Pleroma.Config.get()
 | 
						|
      |> Kernel.*(max_connections)
 | 
						|
      |> round
 | 
						|
      |> max(1)
 | 
						|
 | 
						|
    :telemetry.execute([:pleroma, :connection_pool, :reclaim, :start], %{}, %{
 | 
						|
      max_connections: max_connections,
 | 
						|
      reclaim_max: reclaim_max
 | 
						|
    })
 | 
						|
 | 
						|
    # :ets.fun2ms(
 | 
						|
    # fn {_, {worker_pid, {_, used_by, crf, last_reference}}} when used_by == [] ->
 | 
						|
    #   {worker_pid, crf, last_reference} end)
 | 
						|
    unused_conns =
 | 
						|
      Registry.select(
 | 
						|
        registry(),
 | 
						|
        [
 | 
						|
          {{:_, :"$1", {:_, :"$2", :"$3", :"$4"}}, [{:==, :"$2", []}], [{{:"$1", :"$3", :"$4"}}]}
 | 
						|
        ]
 | 
						|
      )
 | 
						|
 | 
						|
    case unused_conns do
 | 
						|
      [] ->
 | 
						|
        :telemetry.execute(
 | 
						|
          [:pleroma, :connection_pool, :reclaim, :stop],
 | 
						|
          %{reclaimed_count: 0},
 | 
						|
          %{
 | 
						|
            max_connections: max_connections
 | 
						|
          }
 | 
						|
        )
 | 
						|
 | 
						|
        {:stop, :no_unused_conns, nil}
 | 
						|
 | 
						|
      unused_conns ->
 | 
						|
        reclaimed =
 | 
						|
          unused_conns
 | 
						|
          |> Enum.sort(fn {_pid1, crf1, last_reference1}, {_pid2, crf2, last_reference2} ->
 | 
						|
            crf1 <= crf2 and last_reference1 <= last_reference2
 | 
						|
          end)
 | 
						|
          |> Enum.take(reclaim_max)
 | 
						|
 | 
						|
        reclaimed
 | 
						|
        |> Enum.each(fn {pid, _, _} ->
 | 
						|
          DynamicSupervisor.terminate_child(Pleroma.Gun.ConnectionPool.WorkerSupervisor, pid)
 | 
						|
        end)
 | 
						|
 | 
						|
        :telemetry.execute(
 | 
						|
          [:pleroma, :connection_pool, :reclaim, :stop],
 | 
						|
          %{reclaimed_count: Enum.count(reclaimed)},
 | 
						|
          %{max_connections: max_connections}
 | 
						|
        )
 | 
						|
 | 
						|
        {:stop, :normal, nil}
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |