From 60803315d71d52cd33089aa0fd7df62fd23fb0c4 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Sun, 21 Nov 2021 12:27:12 +0200 Subject: [PATCH 1/5] use finch as http client --- lib/ethereumex/config.ex | 7 ++++++- lib/ethereumex/http_client.ex | 9 +++++---- mix.exs | 2 +- mix.lock | 28 ++++++++++++---------------- test/ethereumex/config_test.exs | 6 +++--- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/lib/ethereumex/config.ex b/lib/ethereumex/config.ex index 1bc570c..74bbd74 100644 --- a/lib/ethereumex/config.ex +++ b/lib/ethereumex/config.ex @@ -13,7 +13,12 @@ defmodule Ethereumex.Config do ] end - def setup_children(:http), do: [] + def setup_children(:http) do + [ + {Finch, name: EthereumexFinch} + ] + end + def setup_children(opt), do: raise("Invalid :client option (#{opt}) in config") @spec rpc_url() :: binary() diff --git a/lib/ethereumex/http_client.ex b/lib/ethereumex/http_client.ex index a6ee7df..f7c0f62 100644 --- a/lib/ethereumex/http_client.ex +++ b/lib/ethereumex/http_client.ex @@ -13,14 +13,15 @@ defmodule Ethereumex.HttpClient do def post_request(payload, opts) do headers = [{"Content-Type", "application/json"}] url = Keyword.get(opts, :url) || Config.rpc_url() + request = Finch.build(:post, url, headers, payload) - case HTTPoison.post(url, payload, headers, Config.http_options()) do + case Finch.request(request, EthereumexFinch, Config.http_options()) do {:ok, response} -> - %HTTPoison.Response{body: body, status_code: code} = response + %Finch.Response{body: body, status: code} = response decode_body(body, code) - {:error, %HTTPoison.Error{reason: reason}} -> - {:error, reason} + {:error, error} -> + {:error, error} end end diff --git a/mix.exs b/mix.exs index 8a8ff80..f31842d 100644 --- a/mix.exs +++ b/mix.exs @@ -44,7 +44,7 @@ defmodule Ethereumex.Mixfile do defp deps do [ - {:httpoison, "~> 1.7"}, + {:finch, "~> 0.9"}, {:jason, "~> 1.2"}, {:credo, "~> 1.5", only: [:dev, :test], runtime: false}, {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, diff --git a/mix.lock b/mix.lock index 7a42756..27afbb5 100644 --- a/mix.lock +++ b/mix.lock @@ -1,26 +1,22 @@ %{ "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, - "certifi": {:hex, :certifi, "2.5.3", "70bdd7e7188c804f3a30ee0e7c99655bc35d8ac41c23e12325f36ab449b70651", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "ed516acb3929b101208a9d700062d520f3953da3b6b918d866106ffa980e1c10"}, - "credo": {:hex, :credo, "1.5.4", "9914180105b438e378e94a844ec3a5088ae5875626fc945b7c1462b41afc3198", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cf51af45eadc0a3f39ba13b56fdac415c91b34f7b7533a13dc13550277141bc4"}, - "dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"}, + "castore": {:hex, :castore, "0.1.13", "ccf3ab251ffaebc4319f41d788ce59a6ab3f42b6c27e598ad838ffecee0b04f9", [:mix], [], "hexpm", "a14a7eecfec7e20385493dbb92b0d12c5d77ecfd6307de10102d58c94e8c49c0"}, + "credo": {:hex, :credo, "1.6.1", "7dc76dcdb764a4316c1596804c48eada9fff44bd4b733a91ccbf0c0f368be61e", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "698607fb5993720c7e93d2d8e76f2175bba024de964e160e2f7151ef3ab82ac5"}, + "dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.17", "6f3c7e94170377ba45241d394389e800fb15adc5de51d0a3cd52ae766aafd63f", [:mix], [], "hexpm", "f93ac89c9feca61c165b264b5837bf82344d13bebc634cd575cb711e2e342023"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, - "ex_doc": {:hex, :ex_doc, "0.24.2", "e4c26603830c1a2286dae45f4412a4d1980e1e89dc779fcd0181ed1d5a05c8d9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "e134e1d9e821b8d9e4244687fb2ace58d479b67b282de5158333b0d57c6fb7da"}, + "ex_doc": {:hex, :ex_doc, "0.25.5", "ac3c5425a80b4b7c4dfecdf51fa9c23a44877124dd8ca34ee45ff608b1c6deb9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "688cfa538cdc146bc4291607764a7f1fcfa4cce8009ecd62de03b27197528350"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, - "hackney": {:hex, :hackney, "1.17.0", "717ea195fd2f898d9fe9f1ce0afcc2621a41ecfe137fae57e7fe6e9484b9aa99", [:rebar3], [{:certifi, "~>2.5", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "64c22225f1ea8855f584720c0e5b3cd14095703af1c9fbc845ba042811dc671c"}, - "httpoison": {:hex, :httpoison, "1.7.0", "abba7d086233c2d8574726227b6c2c4f6e53c4deae7fe5f6de531162ce9929a0", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "975cc87c845a103d3d1ea1ccfd68a2700c211a434d8428b10c323dc95dc5b980"}, - "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, + "finch": {:hex, :finch, "0.9.1", "ab2b0151ba88543e221cb50bf0734860db55e8748816ee16e4997fe205f7b315", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6d6b898a59d19f84958eaffec40580f5a9ff88a31e93156707fa8b1d552aa425"}, "jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"}, "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.15.2", "dc72dfe17eb240552857465cc00cce390960d9a0c055c4ccd38b70629227e97c", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "fd23ae48d09b32eff49d4ced2b43c9f086d402ee4fd4fcb2d7fad97fa8823e75"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, - "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, - "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, - "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"}, + "mint": {:hex, :mint, "1.4.0", "cd7d2451b201fc8e4a8fd86257fb3878d9e3752899eb67b0c5b25b180bde1212", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "10a99e144b815cbf8522dccbc8199d15802440fc7a64d67b6853adb6fa170217"}, + "nimble_options": {:hex, :nimble_options, "0.4.0", "c89babbab52221a24b8d1ff9e7d838be70f0d871be823165c94dd3418eea728f", [:mix], [], "hexpm", "e6701c1af326a11eea9634a3b1c62b475339ace9456c1a23ec3bc9a847bca02d"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.2.0", "b44d75e2a6542dcb6acf5d71c32c74ca88960421b6874777f79153bbbbd7dccc", [:mix], [], "hexpm", "52b2871a7515a5ac49b00f214e4165a40724cf99798d8e4a65e4fd64ebd002c1"}, + "nimble_pool": {:hex, :nimble_pool, "0.2.4", "1db8e9f8a53d967d595e0b32a17030cdb6c0dc4a451b8ac787bf601d3f7704c3", [:mix], [], "hexpm", "367e8071e137b787764e6a9992ccb57b276dc2282535f767a07d881951ebeac6"}, "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, - "telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, + "telemetry": {:hex, :telemetry, "1.0.0", "0f453a102cdf13d506b7c0ab158324c337c41f1cc7548f0bc0e130bbf0ae9452", [:rebar3], [], "hexpm", "73bc09fa59b4a0284efb4624335583c528e07ec9ae76aca96ea0673850aec57a"}, "with_env": {:hex, :with_env, "0.1.0", "4c4d4bdf54733917945fa0c521b7a7bbad4f4c65ce75b346a566695898a4f59a", [:mix], [], "hexpm", "2345cf474a963184edb23f626b4f498472c7d9fe5aa2c71473981dc054bdef95"}, } diff --git a/test/ethereumex/config_test.exs b/test/ethereumex/config_test.exs index 3896f4d..86aa41b 100644 --- a/test/ethereumex/config_test.exs +++ b/test/ethereumex/config_test.exs @@ -31,8 +31,8 @@ defmodule Ethereumex.ConfigTest do end end - test ":http has no supervised children" do - assert Ethereumex.Config.setup_children(:http) == [] + test ":http has Finch chiild" do + assert Ethereumex.Config.setup_children(:http) == [{Finch, [name: EthereumexFinch]}] end test "unsupported client types raise an error" do @@ -47,7 +47,7 @@ defmodule Ethereumex.ConfigTest do test "defaults to the configured client_type" do with_env put: [ethereumex: [client_type: :http]] do - assert Ethereumex.Config.setup_children() == [] + assert Ethereumex.Config.setup_children() == [{Finch, [name: EthereumexFinch]}] end end end From d98fc3c84697ee94364c1d4e8545049c30a92de3 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Sun, 21 Nov 2021 12:40:11 +0200 Subject: [PATCH 2/5] add http_pool_options --- config/config.exs | 5 ++++- lib/ethereumex/config.ex | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/config/config.exs b/config/config.exs index 5b148f9..dfe6fa1 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,5 +1,8 @@ use Mix.Config -config :ethereumex, http_options: [timeout: 8000, recv_timeout: 5000] +config :ethereumex, + http_options: [pool_timeout: 5000, receive_timeout: 15_000], + http_pool_options: %{} + # config :ethereumex, ipc_path: "/Library/Application Support/io.parity.ethereum/jsonrpc.ipc" import_config "#{Mix.env()}.exs" diff --git a/lib/ethereumex/config.ex b/lib/ethereumex/config.ex index 74bbd74..a00e1a2 100644 --- a/lib/ethereumex/config.ex +++ b/lib/ethereumex/config.ex @@ -14,8 +14,10 @@ defmodule Ethereumex.Config do end def setup_children(:http) do + pool_opts = http_pool_options() + [ - {Finch, name: EthereumexFinch} + {Finch, name: EthereumexFinch, pools: pool_opts} ] end @@ -81,4 +83,9 @@ defmodule Ethereumex.Config do defp ipc_request_timeout() do Application.get_env(:ethereumex, :ipc_request_timeout, 60_000) end + + @spec http_pool_options() :: map() + defp http_pool_options() do + Application.get_env(:ethereumex, :http_pool_options, %{}) + end end From 5bbae49017cd95d26fb4198f3640f4f5a6145c23 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Sun, 21 Nov 2021 12:54:51 +0200 Subject: [PATCH 3/5] fix dialyzer --- lib/ethereumex/http_client.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ethereumex/http_client.ex b/lib/ethereumex/http_client.ex index f7c0f62..ad7b5a9 100644 --- a/lib/ethereumex/http_client.ex +++ b/lib/ethereumex/http_client.ex @@ -25,7 +25,7 @@ defmodule Ethereumex.HttpClient do end end - @spec decode_body(binary(), integer()) :: {:ok, any()} | http_client_error() + @spec decode_body(binary(), non_neg_integer()) :: {:ok, any()} | http_client_error() defp decode_body(body, code) do case Jason.decode(body) do {:ok, decoded_body} -> From cbc25dae9dd069e1de0068312adaf4141ca03783 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Sun, 21 Nov 2021 12:56:02 +0200 Subject: [PATCH 4/5] update README --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 42b6ff9..3ee2aa9 100644 --- a/README.md +++ b/README.md @@ -45,12 +45,11 @@ config :ethereumex, ``` You can also configure the `HTTP` request timeout for requests sent to the Ethereum JSON-RPC -(you can also overwrite this configuration in `opts` used when calling the client). By default -http requests use no pools, if you want to use hackney default http request pool: +(you can also overwrite this configuration in `opts` used when calling the client). ```elixir config :ethereumex, - http_options: [timeout: 8000, recv_timeout: 5000, hackney: [pool: :default]] + http_options: [pool_timeout: 5000, receive_timeout: 15_000] ``` `:timeout` - timeout to establish a connection, in milliseconds. Default is 8000 From 1ac6c996c1ed2c6b3aa899c0c8d9a88ab0a734cc Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Sun, 21 Nov 2021 14:18:49 +0200 Subject: [PATCH 5/5] fix tests --- test/ethereumex/config_test.exs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/ethereumex/config_test.exs b/test/ethereumex/config_test.exs index 86aa41b..240d403 100644 --- a/test/ethereumex/config_test.exs +++ b/test/ethereumex/config_test.exs @@ -32,7 +32,9 @@ defmodule Ethereumex.ConfigTest do end test ":http has Finch chiild" do - assert Ethereumex.Config.setup_children(:http) == [{Finch, [name: EthereumexFinch]}] + assert Ethereumex.Config.setup_children(:http) == [ + {Finch, [name: EthereumexFinch, pools: %{}]} + ] end test "unsupported client types raise an error" do @@ -47,7 +49,9 @@ defmodule Ethereumex.ConfigTest do test "defaults to the configured client_type" do with_env put: [ethereumex: [client_type: :http]] do - assert Ethereumex.Config.setup_children() == [{Finch, [name: EthereumexFinch]}] + assert Ethereumex.Config.setup_children() == [ + {Finch, [name: EthereumexFinch, pools: %{}]} + ] end end end