From 065bd77fc27281034783e567c100378a94ec63f2 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Sun, 27 Sep 2026 09:48:07 +0200 Subject: [PATCH 1/2] Release 4.8.4 --- NEWS.md | 2 +- src/hackney.app.src | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index fda042bb..9bc052ef 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,6 @@ # NEWS -4.8.4 - UNRELEASED +4.8.4 - 2026-09-27 ------------------ ### Fixed diff --git a/src/hackney.app.src b/src/hackney.app.src index c69c378e..5e7535b7 100644 --- a/src/hackney.app.src +++ b/src/hackney.app.src @@ -4,7 +4,7 @@ {application, hackney, [ {description, "Simple HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support"}, - {vsn, "4.8.3"}, + {vsn, "4.8.4"}, {registered, [hackney_pool]}, {applications, [kernel, stdlib, From 3c80faef5172f82db7e68ee460cf202aa5e82edb Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Sun, 27 Sep 2026 09:53:11 +0200 Subject: [PATCH 2/2] Wait for the pool checkin in h1_request_releases The conn checks itself in with a cast sent after it answers the caller, so reading pool stats right after request/5 raced it on slower runners. --- test/hackney_send_request_tests.erl | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/test/hackney_send_request_tests.erl b/test/hackney_send_request_tests.erl index ca445707..e2463e05 100644 --- a/test/hackney_send_request_tests.erl +++ b/test/hackney_send_request_tests.erl @@ -112,7 +112,10 @@ h1_request_releases() -> try Url = <<"http://localhost:", (integer_to_binary(?H1_PORT))/binary, "/get">>, {ok, 200, _, _} = hackney:request(get, Url, [], <<>>, [{pool, Pool}]), - ?assertMatch(#{in_use_count := 0, free_count := 1}, stats(Pool)) + %% The conn checks itself in with a cast sent after it answers the + %% caller, so the pool can lag request/5 by a moment. + ?assertMatch(#{in_use_count := 0, free_count := 1}, + wait_stats(Pool, fun(#{free_count := F}) -> F =:= 1 end)) after hackney_pool:stop_pool(Pool) end. @@ -120,6 +123,17 @@ h1_request_releases() -> stats(Pool) -> maps:from_list(hackney_pool:get_stats(Pool)). +%% Pool stats once Done holds, or the last stats after 5 s. +wait_stats(Pool, Done) -> + wait_stats(Pool, Done, erlang:monotonic_time(millisecond) + 5000). + +wait_stats(Pool, Done, Deadline) -> + Stats = stats(Pool), + case Done(Stats) orelse erlang:monotonic_time(millisecond) > Deadline of + true -> Stats; + false -> receive after 5 -> ok end, wait_stats(Pool, Done, Deadline) + end. + %% Pull a response with stream_body/1 until it ends. read_chunks(Conn) -> read_chunks(Conn, <<>>).