Skip to content

Commit 5dba1a7

Browse files
authored
Merge pull request #136 from amazon-mq/fix/gh-133-reader-stall
Fix remote reader stall after S3 request timeout (HTTP/1.1 HOL blocking)
2 parents d9370c8 + 5add5c0 commit 5dba1a7

1 file changed

Lines changed: 28 additions & 2 deletions

File tree

src/rabbitmq_stream_s3_api_aws.erl

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -632,8 +632,13 @@ handle_async(
632632
) ->
633633
?LOG_WARNING("S3 request timed out on ~tw/~tw", [Conn, StreamRef]),
634634
counters:add(counter(), ?C_REQUEST_TIMEOUTS, 1),
635-
gun:cancel(Conn, StreamRef),
636-
finish_async(State),
635+
%% gun cannot cancel an HTTP/1.1 stream on the wire - it only stops
636+
%% forwarding events to the owner. The cancelled stream continues to
637+
%% occupy the connection, blocking subsequent requests until its full
638+
%% response is received. Close the whole connection instead; the pool
639+
%% observes the 'DOWN' and opens a fresh replacement.
640+
gun:close(Conn),
641+
finish_async_close(State),
637642
{done_cancel, {error, timeout}}.
638643

639644
-spec cancel_async(async_req(), async_state()) -> ok.
@@ -679,6 +684,27 @@ finish_async(#{conn := Conn, pool := Pool} = State) ->
679684
counters:sub(counter(), ?C_ACTIVE_REQUESTS, 1),
680685
ok = rabbitmq_stream_s3_api_aws_pool:checkin(Pool, Conn).
681686

687+
%% Finish an async request when the connection is being closed (e.g. on
688+
%% timeout). Same bookkeeping as `finish_async` but omits the pool checkin -
689+
%% the pool's 'DOWN' handler removes the conn and grows a replacement.
690+
finish_async_close(State) ->
691+
case State of
692+
#{timer_ref := TimerRef, stream_ref := StreamRef} ->
693+
case erlang:cancel_timer(TimerRef) of
694+
false ->
695+
receive
696+
{request_timeout, StreamRef} -> ok
697+
after 0 -> ok
698+
end;
699+
_ ->
700+
ok
701+
end;
702+
_ ->
703+
ok
704+
end,
705+
counters:sub(counter(), ?C_ACTIVE_REQUESTS, 1),
706+
ok.
707+
682708
-spec request(http_method(), key(), req_headers(), iodata(), request_opts()) ->
683709
{ok, http_response()}
684710
| {error, any()}.

0 commit comments

Comments
 (0)