move to 2.5.5
[anni] / lib / pleroma / http / adapter_helper / gun.ex
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
5 defmodule Pleroma.HTTP.AdapterHelper.Gun do
6   @behaviour Pleroma.HTTP.AdapterHelper
7
8   alias Pleroma.Config
9   alias Pleroma.HTTP.AdapterHelper
10
11   require Logger
12
13   @defaults [
14     retry: 1,
15     retry_timeout: 1_000
16   ]
17
18   @type pool() :: :federation | :upload | :media | :default
19
20   @spec options(keyword(), URI.t()) :: keyword()
21   def options(incoming_opts \\ [], %URI{} = uri) do
22     proxy =
23       [:http, :proxy_url]
24       |> Config.get()
25       |> AdapterHelper.format_proxy()
26
27     config_opts = Config.get([:http, :adapter], [])
28
29     @defaults
30     |> Keyword.merge(config_opts)
31     |> add_scheme_opts(uri)
32     |> AdapterHelper.maybe_add_proxy(proxy)
33     |> Keyword.merge(incoming_opts)
34     |> put_timeout()
35   end
36
37   defp add_scheme_opts(opts, %{scheme: "http"}), do: opts
38
39   defp add_scheme_opts(opts, %{scheme: "https"}) do
40     Keyword.put(opts, :certificates_verification, true)
41   end
42
43   defp put_timeout(opts) do
44     {recv_timeout, opts} = Keyword.pop(opts, :recv_timeout, pool_timeout(opts[:pool]))
45     # this is the timeout to receive a message from Gun
46     # `:timeout` key is used in Tesla
47     Keyword.put(opts, :timeout, recv_timeout)
48   end
49
50   @spec pool_timeout(pool()) :: non_neg_integer()
51   def pool_timeout(pool) do
52     default = Config.get([:pools, :default, :recv_timeout], 5_000)
53
54     Config.get([:pools, pool, :recv_timeout], default)
55   end
56
57   def limiter_setup do
58     prefix = Pleroma.Gun.ConnectionPool
59     wait = Config.get([:connections_pool, :connection_acquisition_wait])
60     retries = Config.get([:connections_pool, :connection_acquisition_retries])
61
62     :pools
63     |> Config.get([])
64     |> Enum.each(fn {name, opts} ->
65       max_running = Keyword.get(opts, :size, 50)
66       max_waiting = Keyword.get(opts, :max_waiting, 10)
67
68       result =
69         ConcurrentLimiter.new(:"#{prefix}.#{name}", max_running, max_waiting,
70           wait: wait,
71           max_retries: retries
72         )
73
74       case result do
75         :ok -> :ok
76         {:error, :existing} -> :ok
77       end
78     end)
79
80     :ok
81   end
82 end