diff options
author | Alex S <alex.strizhakov@gmail.com> | 2019-08-14 13:37:27 +0300 |
---|---|---|
committer | Ariadne Conill <ariadne@dereferenced.org> | 2019-08-18 22:34:13 +0000 |
commit | aa0ab31b5ba24f9d482847193a309037907bb71d (patch) | |
tree | 0fd55bf4cd3ec33907fd369bb96accaeacb04f76 | |
parent | 246906165776874ca7e4064b197ddf1237af2d1c (diff) | |
download | pleroma-aa0ab31b5ba24f9d482847193a309037907bb71d.tar.gz |
added gun connections holder genserver
-rw-r--r-- | lib/pleroma/application.ex | 3 | ||||
-rw-r--r-- | lib/pleroma/gun/connections.ex | 25 | ||||
-rw-r--r-- | lib/pleroma/http/http.ex | 23 | ||||
-rw-r--r-- | test/gun/connections_test.exs | 57 | ||||
-rw-r--r-- | test/reverse_proxy/reverse_proxy_test.exs | 7 |
5 files changed, 99 insertions, 16 deletions
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 25e56b9e2..f755a1355 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -35,7 +35,8 @@ defmodule Pleroma.Application do Pleroma.Emoji, Pleroma.Captcha, Pleroma.FlakeId, - Pleroma.ScheduledActivityWorker + Pleroma.ScheduledActivityWorker, + Pleroma.Gun.Connections ] ++ cachex_children() ++ hackney_pool_children() ++ diff --git a/lib/pleroma/gun/connections.ex b/lib/pleroma/gun/connections.ex index 60ec68d89..d5a9d8607 100644 --- a/lib/pleroma/gun/connections.ex +++ b/lib/pleroma/gun/connections.ex @@ -26,8 +26,8 @@ defmodule Pleroma.Gun.Connections do {:ok, %__MODULE__{conns: %{}}} end - @spec get_conn(atom(), String.t(), keyword()) :: pid() - def get_conn(name \\ __MODULE__, url, opts \\ []) do + @spec get_conn(String.t(), keyword(), atom()) :: pid() + def get_conn(url, opts \\ [], name \\ __MODULE__) do opts = Enum.into(opts, %{}) uri = URI.parse(url) @@ -39,6 +39,27 @@ defmodule Pleroma.Gun.Connections do ) end + # TODO: only for testing, add this parameter to the config + @spec try_to_get_gun_conn(String.t(), keyword(), atom()) :: nil | pid() + def try_to_get_gun_conn(url, opts \\ [], name \\ __MODULE__), + do: try_to_get_gun_conn(url, opts, name, 0) + + @spec try_to_get_gun_conn(String.t(), keyword(), atom(), pos_integer()) :: nil | pid() + def try_to_get_gun_conn(_url, _, _, 3), do: nil + + def try_to_get_gun_conn(url, opts, name, acc) do + case Pleroma.Gun.Connections.get_conn(url, opts, name) do + nil -> try_to_get_gun_conn(url, acc + 1) + conn -> conn + end + end + + @spec alive?(atom()) :: boolean() + def alive?(name \\ __MODULE__) do + pid = Process.whereis(name) + if pid, do: Process.alive?(pid), else: false + end + @spec get_state(atom()) :: t() def get_state(name \\ __MODULE__) do GenServer.call(name, {:state}) diff --git a/lib/pleroma/http/http.ex b/lib/pleroma/http/http.ex index 6d7934841..1846749c0 100644 --- a/lib/pleroma/http/http.ex +++ b/lib/pleroma/http/http.ex @@ -32,6 +32,15 @@ defmodule Pleroma.HTTP do process_request_options(options) |> process_sni_options(url) + adapter_gun? = Application.get_env(:tesla, :adapter) == Tesla.Adapter.Gun + + options = + if adapter_gun? and Pleroma.Gun.Connections.alive?() do + get_conn_for_gun(url, options) + else + options + end + params = Keyword.get(options, :params, []) %{} @@ -52,6 +61,20 @@ defmodule Pleroma.HTTP do end end + defp get_conn_for_gun(url, options) do + case Pleroma.Gun.Connections.try_to_get_gun_conn(url) do + nil -> + options + + conn -> + adapter_opts = + Keyword.get(options, :adapter, []) + |> Keyword.put(:conn, conn) + + Keyword.put(options, :adapter, adapter_opts) + end + end + defp process_sni_options(options, nil), do: options defp process_sni_options(options, url) do diff --git a/test/gun/connections_test.exs b/test/gun/connections_test.exs index 2ec8f3993..42354d330 100644 --- a/test/gun/connections_test.exs +++ b/test/gun/connections_test.exs @@ -3,23 +3,56 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Gun.ConnectionsTest do - use ExUnit.Case, async: true + use ExUnit.Case alias Pleroma.Gun.{Connections, Conn, API} setup do name = :test_gun_connections + adapter = Application.get_env(:tesla, :adapter) + Application.put_env(:tesla, :adapter, Tesla.Adapter.Gun) + on_exit(fn -> Application.put_env(:tesla, :adapter, adapter) end) {:ok, pid} = Connections.start_link(name) {:ok, name: name, pid: pid} end + describe "alive?/2" do + test "is alive", %{name: name} do + assert Connections.alive?(name) + end + + test "returns false if not started" do + refute Connections.alive?(:some_random_name) + end + end + + test "try_to_get_gun_conn/1 returns conn", %{name: name, pid: pid} do + conn = Connections.try_to_get_gun_conn("http://some-domain.com", [genserver_pid: pid], name) + assert is_pid(conn) + assert Process.alive?(conn) + + reused_conn = Connections.get_conn("http://some-domain.com", [genserver_pid: pid], name) + + assert conn == reused_conn + + %Connections{ + conns: %{ + "some-domain.com:80" => %Conn{ + conn: ^conn, + state: :up, + waiting_pids: [] + } + } + } = Connections.get_state(name) + end + test "opens connection and reuse it on next request", %{name: name, pid: pid} do - conn = Connections.get_conn(name, "http://some-domain.com", genserver_pid: pid) + conn = Connections.get_conn("http://some-domain.com", [genserver_pid: pid], name) assert is_pid(conn) assert Process.alive?(conn) - reused_conn = Connections.get_conn(name, "http://some-domain.com", genserver_pid: pid) + reused_conn = Connections.get_conn("http://some-domain.com", [genserver_pid: pid], name) assert conn == reused_conn @@ -35,15 +68,15 @@ defmodule Gun.ConnectionsTest do end test "reuses connection based on protocol", %{name: name, pid: pid} do - conn = Connections.get_conn(name, "http://some-domain.com", genserver_pid: pid) + conn = Connections.get_conn("http://some-domain.com", [genserver_pid: pid], name) assert is_pid(conn) assert Process.alive?(conn) - https_conn = Connections.get_conn(name, "https://some-domain.com", genserver_pid: pid) + https_conn = Connections.get_conn("https://some-domain.com", [genserver_pid: pid], name) refute conn == https_conn - reused_https = Connections.get_conn(name, "https://some-domain.com", genserver_pid: pid) + reused_https = Connections.get_conn("https://some-domain.com", [genserver_pid: pid], name) refute conn == reused_https @@ -66,7 +99,7 @@ defmodule Gun.ConnectionsTest do end test "process gun_down message", %{name: name, pid: pid} do - conn = Connections.get_conn(name, "http://gun_down.com", genserver_pid: pid) + conn = Connections.get_conn("http://gun_down.com", [genserver_pid: pid], name) refute conn @@ -82,7 +115,7 @@ defmodule Gun.ConnectionsTest do end test "process gun_down message and then gun_up", %{name: name, pid: pid} do - conn = Connections.get_conn(name, "http://gun_down_and_up.com", genserver_pid: pid) + conn = Connections.get_conn("http://gun_down_and_up.com", [genserver_pid: pid], name) refute conn @@ -96,7 +129,7 @@ defmodule Gun.ConnectionsTest do } } = Connections.get_state(name) - conn = Connections.get_conn(name, "http://gun_down_and_up.com", genserver_pid: pid) + conn = Connections.get_conn("http://gun_down_and_up.com", [genserver_pid: pid], name) assert is_pid(conn) assert Process.alive?(conn) @@ -116,7 +149,7 @@ defmodule Gun.ConnectionsTest do tasks = for _ <- 1..5 do Task.async(fn -> - Connections.get_conn(name, "http://some-domain.com", genserver_pid: pid) + Connections.get_conn("http://some-domain.com", [genserver_pid: pid], name) end) end @@ -149,12 +182,12 @@ defmodule Gun.ConnectionsTest do api = Pleroma.Config.get([API]) Pleroma.Config.put([API], :gun) on_exit(fn -> Pleroma.Config.put([API], api) end) - conn = Connections.get_conn(name, "http://httpbin.org") + conn = Connections.get_conn("http://httpbin.org", [], name) assert is_pid(conn) assert Process.alive?(conn) - reused_conn = Connections.get_conn(name, "http://httpbin.org") + reused_conn = Connections.get_conn("http://httpbin.org", [], name) assert conn == reused_conn diff --git a/test/reverse_proxy/reverse_proxy_test.exs b/test/reverse_proxy/reverse_proxy_test.exs index c2430a2b8..91cf5c1c8 100644 --- a/test/reverse_proxy/reverse_proxy_test.exs +++ b/test/reverse_proxy/reverse_proxy_test.exs @@ -3,7 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.ReverseProxyTest do - use Pleroma.Web.ConnCase, async: true + use Pleroma.Web.ConnCase import ExUnit.CaptureLog import Mox alias Pleroma.ReverseProxy @@ -322,6 +322,10 @@ defmodule Pleroma.ReverseProxyTest do adapter = Application.get_env(:tesla, :adapter) Application.put_env(:tesla, :adapter, Tesla.Adapter.Gun) + api = Pleroma.Config.get([Pleroma.Gun.API]) + Pleroma.Config.put([Pleroma.Gun.API], :gun) + {:ok, _} = Pleroma.Gun.Connections.start_link(Pleroma.Gun.Connections) + conn = ReverseProxy.call(conn, "http://httpbin.org/stream-bytes/10") assert byte_size(conn.resp_body) == 10 @@ -331,6 +335,7 @@ defmodule Pleroma.ReverseProxyTest do on_exit(fn -> Pleroma.Config.put([Pleroma.ReverseProxy.Client], client) Application.put_env(:tesla, :adapter, adapter) + Pleroma.Config.put([Pleroma.Gun.API], api) end) end end |