changed
CHANGELOG.md
|
@@ -1,5 1,15 @@
|
1
1
|
# Changelog
|
2
2
|
|
3
|
## v0.18.0 (2024-02-09)
|
4
|
|
5
|
### Enhancements
|
6
|
|
7
|
- Add Finch name to telemetry events #252
|
8
|
|
9
|
### Bug Fixes
|
10
|
|
11
|
- Fix several minor dialyzer errors and run dialyzer in CI #259, #261
|
12
|
|
3
13
|
## v0.17.0 (2024-01-07)
|
4
14
|
|
5
15
|
### Enhancements
|
changed
README.md
|
@@ -107,7 107,7 @@ The package can be installed by adding `finch` to your list of dependencies in `
|
107
107
|
```elixir
|
108
108
|
def deps do
|
109
109
|
[
|
110
|
- {:finch, "~> 0.17"}
|
110
|
{:finch, "~> 0.18"}
|
111
111
|
]
|
112
112
|
end
|
113
113
|
```
|
changed
hex_metadata.config
|
@@ -2,7 2,7 @@
|
2
2
|
[{<<"Changelog">>,<<"https://hexdocs.pm/finch/changelog.html">>},
|
3
3
|
{<<"GitHub">>,<<"https://github.com/sneako/finch">>}]}.
|
4
4
|
{<<"name">>,<<"finch">>}.
|
5
|
- {<<"version">>,<<"0.17.0">>}.
|
5
|
{<<"version">>,<<"0.18.0">>}.
|
6
6
|
{<<"description">>,<<"An HTTP client focused on performance.">>}.
|
7
7
|
{<<"elixir">>,<<"~> 1.11">>}.
|
8
8
|
{<<"app">>,<<"finch">>}.
|
|
@@ -44,8 44,8 @@
|
44
44
|
<<"lib/finch/http1/pool_metrics.ex">>,<<"lib/finch/http2">>,
|
45
45
|
<<"lib/finch/http2/request_stream.ex">>,<<"lib/finch/http2/pool.ex">>,
|
46
46
|
<<"lib/finch/http2/pool_metrics.ex">>,<<"lib/finch/request.ex">>,
|
47
|
- <<"lib/finch/ssl.ex">>,<<"lib/finch/telemetry.ex">>,
|
48
|
- <<"lib/finch/response.ex">>,<<"lib/finch/pool.ex">>,
|
49
|
- <<"lib/finch/pool_manager.ex">>,<<"lib/finch.ex">>,<<".formatter.exs">>,
|
47
|
<<"lib/finch/ssl.ex">>,<<"lib/finch/response.ex">>,
|
48
|
<<"lib/finch/pool_manager.ex">>,<<"lib/finch/pool.ex">>,
|
49
|
<<"lib/finch/telemetry.ex">>,<<"lib/finch.ex">>,<<".formatter.exs">>,
|
50
50
|
<<"mix.exs">>,<<"README.md">>,<<"LICENSE.md">>,<<"CHANGELOG.md">>]}.
|
51
51
|
{<<"build_tools">>,[<<"mix">>]}.
|
changed
lib/finch.ex
|
@@ -90,7 90,7 @@ defmodule Finch do
|
90
90
|
],
|
91
91
|
start_pool_metrics?: [
|
92
92
|
type: :boolean,
|
93
|
- doc: "When true, pool metrics will be collected and avaiable through Finch.pool_status/2",
|
93
|
doc: "When true, pool metrics will be collected and available through Finch.pool_status/2",
|
94
94
|
default: false
|
95
95
|
]
|
96
96
|
]
|
|
@@ -104,7 104,7 @@ defmodule Finch do
|
104
104
|
|
105
105
|
@type scheme_host_port() :: {scheme(), host :: String.t(), port :: :inet.port_number()}
|
106
106
|
|
107
|
- @type request_opt() :: {:pool_timeout, pos_integer()} | {:receive_timeout, pos_integer()}
|
107
|
@type request_opt() :: {:pool_timeout, timeout()} | {:receive_timeout, timeout()}
|
108
108
|
|
109
109
|
@typedoc """
|
110
110
|
Options used by request functions.
|
|
@@ -360,10 360,9 @@ defmodule Finch do
|
360
360
|
{:ok, acc} | {:error, Exception.t()}
|
361
361
|
when acc: term()
|
362
362
|
def stream(%Request{} = req, name, acc, fun, opts \\ []) when is_function(fun, 2) do
|
363
|
- fun =
|
364
|
- fn entry, acc ->
|
365
|
- {:cont, fun.(entry, acc)}
|
366
|
- end
|
363
|
fun = fn entry, acc ->
|
364
|
{:cont, fun.(entry, acc)}
|
365
|
end
|
367
366
|
|
368
367
|
stream_while(req, name, acc, fun, opts)
|
369
368
|
end
|
|
@@ -427,7 426,7 @@ defmodule Finch do
|
427
426
|
|
428
427
|
defp __stream__(%Request{} = req, name, acc, fun, opts) do
|
429
428
|
{pool, pool_mod} = get_pool(req, name)
|
430
|
- pool_mod.request(pool, req, acc, fun, opts)
|
429
|
pool_mod.request(pool, req, acc, fun, name, opts)
|
431
430
|
end
|
432
431
|
|
433
432
|
@doc """
|
|
@@ -560,7 559,7 @@ defmodule Finch do
|
560
559
|
@spec async_request(Request.t(), name(), request_opts()) :: request_ref()
|
561
560
|
def async_request(%Request{} = req, name, opts \\ []) do
|
562
561
|
{pool, pool_mod} = get_pool(req, name)
|
563
|
- pool_mod.async_request(pool, req, opts)
|
562
|
pool_mod.async_request(pool, req, name, opts)
|
564
563
|
end
|
565
564
|
|
566
565
|
@doc """
|
changed
lib/finch/http1/conn.ex
|
@@ -17,22 17,24 @@ defmodule Finch.HTTP1.Conn do
|
17
17
|
}
|
18
18
|
end
|
19
19
|
|
20
|
- def connect(%{mint: mint} = conn) when not is_nil(mint) do
|
20
|
def connect(%{mint: mint} = conn, name) when not is_nil(mint) do
|
21
21
|
meta = %{
|
22
22
|
scheme: conn.scheme,
|
23
23
|
host: conn.host,
|
24
|
- port: conn.port
|
24
|
port: conn.port,
|
25
|
name: name
|
25
26
|
}
|
26
27
|
|
27
28
|
Telemetry.event(:reused_connection, %{}, meta)
|
28
29
|
{:ok, conn}
|
29
30
|
end
|
30
31
|
|
31
|
- def connect(%{mint: nil} = conn) do
|
32
|
def connect(%{mint: nil} = conn, name) do
|
32
33
|
meta = %{
|
33
34
|
scheme: conn.scheme,
|
34
35
|
host: conn.host,
|
35
|
- port: conn.port
|
36
|
port: conn.port,
|
37
|
name: name
|
36
38
|
}
|
37
39
|
|
38
40
|
start_time = Telemetry.start(:connect, meta)
|
|
@@ -98,12 100,12 @@ defmodule Finch.HTTP1.Conn do
|
98
100
|
end
|
99
101
|
end
|
100
102
|
|
101
|
- def request(%{mint: nil} = conn, _, _, _, _, _, _), do: {:error, conn, "Could not connect"}
|
103
|
def request(%{mint: nil} = conn, _, _, _, _, _, _, _), do: {:error, conn, "Could not connect"}
|
102
104
|
|
103
|
- def request(conn, req, acc, fun, receive_timeout, request_timeout, idle_time) do
|
105
|
def request(conn, req, acc, fun, name, receive_timeout, request_timeout, idle_time) do
|
104
106
|
full_path = Finch.Request.request_path(req)
|
105
107
|
|
106
|
- metadata = %{request: req}
|
108
|
metadata = %{request: req, name: name}
|
107
109
|
|
108
110
|
extra_measurements = %{idle_time: idle_time}
|
changed
lib/finch/http1/pool.ex
|
@@ -16,8 16,7 @@ defmodule Finch.HTTP1.Pool do
|
16
16
|
pool_max_idle_time,
|
17
17
|
_start_pool_metrics?,
|
18
18
|
_pool_idx
|
19
|
- } =
|
20
|
- opts
|
19
|
} = opts
|
21
20
|
|
22
21
|
%{
|
23
22
|
id: __MODULE__,
|
|
@@ -40,12 39,13 @@ defmodule Finch.HTTP1.Pool do
|
40
39
|
end
|
41
40
|
|
42
41
|
@impl Finch.Pool
|
43
|
- def request(pool, req, acc, fun, opts) do
|
42
|
def request(pool, req, acc, fun, name, opts) do
|
44
43
|
pool_timeout = Keyword.get(opts, :pool_timeout, 5_000)
|
45
44
|
receive_timeout = Keyword.get(opts, :receive_timeout, 15_000)
|
46
45
|
request_timeout = Keyword.get(opts, :request_timeout, :infinity)
|
47
46
|
|
48
|
- metadata = %{request: req, pool: pool}
|
47
|
metadata = %{request: req, pool: pool, name: name}
|
48
|
|
49
49
|
start_time = Telemetry.start(:queue, metadata)
|
50
50
|
|
51
51
|
try do
|
|
@@ -55,9 55,18 @@ defmodule Finch.HTTP1.Pool do
|
55
55
|
fn from, {state, conn, idle_time} ->
|
56
56
|
Telemetry.stop(:queue, start_time, metadata, %{idle_time: idle_time})
|
57
57
|
|
58
|
- with {:ok, conn} <- Conn.connect(conn),
|
58
|
with {:ok, conn} <- Conn.connect(conn, name),
|
59
59
|
{:ok, conn, acc} <-
|
60
|
- Conn.request(conn, req, acc, fun, receive_timeout, request_timeout, idle_time) do
|
60
|
Conn.request(
|
61
|
conn,
|
62
|
req,
|
63
|
acc,
|
64
|
fun,
|
65
|
name,
|
66
|
receive_timeout,
|
67
|
request_timeout,
|
68
|
idle_time
|
69
|
) do
|
61
70
|
{{:ok, acc}, transfer_if_open(conn, state, from)}
|
62
71
|
else
|
63
72
|
{:error, conn, error} ->
|
|
@@ -90,7 99,7 @@ defmodule Finch.HTTP1.Pool do
|
90
99
|
end
|
91
100
|
|
92
101
|
@impl Finch.Pool
|
93
|
- def async_request(pool, req, opts) do
|
102
|
def async_request(pool, req, name, opts) do
|
94
103
|
owner = self()
|
95
104
|
|
96
105
|
pid =
|
|
@@ -103,6 112,7 @@ defmodule Finch.HTTP1.Pool do
|
103
112
|
req,
|
104
113
|
{owner, monitor, request_ref},
|
105
114
|
&send_async_response/2,
|
115
|
name,
|
106
116
|
opts
|
107
117
|
) do
|
108
118
|
{:ok, _} -> send(owner, {request_ref, :done})
|
changed
lib/finch/http1/pool_metrics.ex
|
@@ -45,7 45,7 @@ defmodule Finch.HTTP1.PoolMetrics do
|
45
45
|
|
46
46
|
def maybe_add(nil, _metrics_list), do: :ok
|
47
47
|
|
48
|
- def maybe_add(ref, metrics_list) when is_reference(ref) do
|
48
|
def maybe_add(ref, metrics_list) do
|
49
49
|
Enum.each(metrics_list, fn {metric_name, val} ->
|
50
50
|
:atomics.add(ref, @atomic_idx[metric_name], val)
|
51
51
|
end)
|
|
@@ -57,7 57,9 @@ defmodule Finch.HTTP1.PoolMetrics do
|
57
57
|
|> get_pool_status()
|
58
58
|
end
|
59
59
|
|
60
|
- def get_pool_status(ref) when is_reference(ref) do
|
60
|
def get_pool_status(nil), do: {:error, :not_found}
|
61
|
|
62
|
def get_pool_status(ref) do
|
61
63
|
%{
|
62
64
|
pool_idx: pool_idx,
|
63
65
|
pool_size: pool_size,
|
|
@@ -76,6 78,4 @@ defmodule Finch.HTTP1.PoolMetrics do
|
76
78
|
|
77
79
|
{:ok, result}
|
78
80
|
end
|
79
|
-
|
80
|
- def get_pool_status(nil), do: {:error, :not_found}
|
81
81
|
end
|
changed
lib/finch/http2/pool.ex
|
@@ -30,7 30,7 @@ defmodule Finch.HTTP2.Pool do
|
30
30
|
# Call the pool with the request. The pool will multiplex multiple requests
|
31
31
|
# and stream the result set back to the calling process using `send`
|
32
32
|
@impl Finch.Pool
|
33
|
- def request(pool, request, acc, fun, opts) do
|
33
|
def request(pool, request, acc, fun, name, opts) do
|
34
34
|
opts = Keyword.put_new(opts, :receive_timeout, @default_receive_timeout)
|
35
35
|
timeout = opts[:receive_timeout]
|
36
36
|
request_ref = make_request_ref(pool)
|
|
@@ -48,7 48,8 @@ defmodule Finch.HTTP2.Pool do
|
48
48
|
response_waiting_loop(acc, fun, request_ref, monitor, fail_safe_timeout, :headers)
|
49
49
|
catch
|
50
50
|
kind, error ->
|
51
|
- Telemetry.exception(:recv, recv_start, kind, error, __STACKTRACE__, %{request: request})
|
51
|
metadata = %{request: request, name: name}
|
52
|
Telemetry.exception(:recv, recv_start, kind, error, __STACKTRACE__, metadata)
|
52
53
|
|
53
54
|
:ok = :gen_statem.call(pool, {:cancel, request_ref})
|
54
55
|
clean_responses(request_ref)
|
|
@@ -60,7 61,7 @@ defmodule Finch.HTTP2.Pool do
|
60
61
|
end
|
61
62
|
|
62
63
|
@impl Finch.Pool
|
63
|
- def async_request(pool, req, opts) do
|
64
|
def async_request(pool, req, _name, opts) do
|
64
65
|
opts = Keyword.put_new(opts, :receive_timeout, @default_receive_timeout)
|
65
66
|
request_ref = make_request_ref(pool)
|
66
67
|
|
|
@@ -264,7 265,8 @@ defmodule Finch.HTTP2.Pool do
|
264
265
|
metadata = %{
|
265
266
|
scheme: data.scheme,
|
266
267
|
host: data.host,
|
267
|
- port: data.port
|
268
|
port: data.port,
|
269
|
name: data.finch_name
|
268
270
|
}
|
269
271
|
|
270
272
|
start = Telemetry.start(:connect, metadata)
|
|
@@ -529,7 531,7 @@ defmodule Finch.HTTP2.Pool do
|
529
531
|
end
|
530
532
|
|
531
533
|
defp send_request(from, from_pid, request_ref, req, opts, data) do
|
532
|
- telemetry_metadata = %{request: req}
|
534
|
telemetry_metadata = %{request: req, name: data.finch_name}
|
533
535
|
|
534
536
|
request = %{
|
535
537
|
stream: RequestStream.new(req.body),
|
changed
lib/finch/http2/pool_metrics.ex
|
@@ -35,7 35,7 @@ defmodule Finch.HTTP2.PoolMetrics do
|
35
35
|
|
36
36
|
def maybe_add(nil, _metrics_list), do: :ok
|
37
37
|
|
38
|
- def maybe_add(ref, metrics_list) when is_reference(ref) do
|
38
|
def maybe_add(ref, metrics_list) do
|
39
39
|
Enum.each(metrics_list, fn {metric_name, val} ->
|
40
40
|
:atomics.add(ref, @atomic_idx[metric_name], val)
|
41
41
|
end)
|
|
@@ -47,7 47,9 @@ defmodule Finch.HTTP2.PoolMetrics do
|
47
47
|
|> get_pool_status()
|
48
48
|
end
|
49
49
|
|
50
|
- def get_pool_status(ref) when is_reference(ref) do
|
50
|
def get_pool_status(nil), do: {:error, :not_found}
|
51
|
|
52
|
def get_pool_status(ref) do
|
51
53
|
%{
|
52
54
|
pool_idx: pool_idx,
|
53
55
|
in_flight_requests: in_flight_requests
|
|
@@ -63,6 65,4 @@ defmodule Finch.HTTP2.PoolMetrics do
|
63
65
|
|
64
66
|
{:ok, result}
|
65
67
|
end
|
66
|
-
|
67
|
- def get_pool_status(nil), do: {:error, :not_found}
|
68
68
|
end
|
changed
lib/finch/pool.ex
|
@@ -9,12 9,17 @@ defmodule Finch.Pool do
|
9
9
|
Finch.Request.t(),
|
10
10
|
acc,
|
11
11
|
Finch.stream(acc),
|
12
|
Finch.name(),
|
12
13
|
list()
|
13
|
- ) ::
|
14
|
- {:ok, acc} | {:error, term()}
|
14
|
) :: {:ok, acc} | {:error, term()}
|
15
15
|
when acc: term()
|
16
16
|
|
17
|
- @callback async_request(pid(), Finch.Request.t(), list()) :: request_ref()
|
17
|
@callback async_request(
|
18
|
pid(),
|
19
|
Finch.Request.t(),
|
20
|
Finch.name(),
|
21
|
list()
|
22
|
) :: request_ref()
|
18
23
|
|
19
24
|
@callback cancel_async_request(request_ref()) :: :ok
|
changed
lib/finch/telemetry.ex
|
@@ -63,6 63,7 @@ defmodule Finch.Telemetry do
|
63
63
|
|
64
64
|
#### Metadata
|
65
65
|
|
66
|
* `:name` - The name of the Finch instance.
|
66
67
|
* `:pool` - The pool's PID.
|
67
68
|
* `:request` - The request (`Finch.Request`).
|
68
69
|
|
|
@@ -77,6 78,7 @@ defmodule Finch.Telemetry do
|
77
78
|
|
78
79
|
#### Metadata
|
79
80
|
|
81
|
* `:name` - The name of the Finch instance.
|
80
82
|
* `:pool` - The pool's PID.
|
81
83
|
* `:request` - The request (`Finch.Request`).
|
82
84
|
|
|
@@ -90,6 92,7 @@ defmodule Finch.Telemetry do
|
90
92
|
|
91
93
|
#### Metadata
|
92
94
|
|
95
|
* `:name` - The name of the Finch instance.
|
93
96
|
* `:request` - The request (`Finch.Request`).
|
94
97
|
* `:kind` - The type of exception.
|
95
98
|
* `:reason` - Error description or error data.
|
|
@@ -106,6 109,7 @@ defmodule Finch.Telemetry do
|
106
109
|
|
107
110
|
#### Metadata
|
108
111
|
|
112
|
* `:name` - The name of the Finch instance.
|
109
113
|
* `:scheme` - The scheme used in the connection. either `http` or `https`.
|
110
114
|
* `:host` - The host address.
|
111
115
|
* `:port` - The port to connect on.
|
|
@@ -120,6 124,7 @@ defmodule Finch.Telemetry do
|
120
124
|
|
121
125
|
#### Metadata
|
122
126
|
|
127
|
* `:name` - The name of the Finch instance.
|
123
128
|
* `:scheme` - The scheme used in the connection. either `http` or `https`.
|
124
129
|
* `:host` - The host address.
|
125
130
|
* `:port` - The port to connect on.
|
|
@@ -131,6 136,7 @@ defmodule Finch.Telemetry do
|
131
136
|
|
132
137
|
#### Measurements
|
133
138
|
|
139
|
* `:name` - The name of the Finch instance.
|
134
140
|
* `:system_time` - The system time.
|
135
141
|
* `:idle_time` - Elapsed time since the connection was last checked in or initialized.
|
136
142
|
|
|
@@ -144,6 150,7 @@ defmodule Finch.Telemetry do
|
144
150
|
|
145
151
|
#### Measurements
|
146
152
|
|
153
|
* `:name` - The name of the Finch instance.
|
147
154
|
* `:duration` - Time taken to make the request.
|
148
155
|
* `:idle_time` - Elapsed time since the connection was last checked in or initialized.
|
149
156
|
|
|
@@ -163,6 170,7 @@ defmodule Finch.Telemetry do
|
163
170
|
|
164
171
|
#### Metadata
|
165
172
|
|
173
|
* `:name` - The name of the Finch instance.
|
166
174
|
* `:request` - The request (`Finch.Request`).
|
167
175
|
|
168
176
|
### Receive Stop
|
|
@@ -176,6 184,7 @@ defmodule Finch.Telemetry do
|
176
184
|
|
177
185
|
#### Metadata
|
178
186
|
|
187
|
* `:name` - The name of the Finch instance.
|
179
188
|
* `:request` - The request (`Finch.Request`).
|
180
189
|
* `:status` - The response status (`Mint.Types.status()`).
|
181
190
|
* `:headers` - The response headers (`Mint.Types.headers()`).
|
|
@@ -192,6 201,7 @@ defmodule Finch.Telemetry do
|
192
201
|
|
193
202
|
#### Metadata
|
194
203
|
|
204
|
* `:name` - The name of the Finch instance.
|
195
205
|
* `:request` - The request (`Finch.Request`).
|
196
206
|
* `:kind` - The type of exception.
|
197
207
|
* `:reason` - Error description or error data.
|
|
@@ -203,6 213,7 @@ defmodule Finch.Telemetry do
|
203
213
|
|
204
214
|
#### Metadata
|
205
215
|
|
216
|
* `:name` - The name of the Finch instance.
|
206
217
|
* `:scheme` - The scheme used in the connection. either `http` or `https`.
|
207
218
|
* `:host` - The host address.
|
208
219
|
* `:port` - The port to connect on.
|
changed
mix.exs
|
@@ -2,7 2,7 @@ defmodule Finch.MixProject do
|
2
2
|
use Mix.Project
|
3
3
|
|
4
4
|
@name "Finch"
|
5
|
- @version "0.17.0"
|
5
|
@version "0.18.0"
|
6
6
|
@repo_url "https://github.com/sneako/finch"
|
7
7
|
|
8
8
|
def project do
|