|
14 | 14 | -behaviour(gen_server). |
15 | 15 |
|
16 | 16 | -export([start_link/2, connect/1, open_channel/3, hard_error_in_channel/3, |
17 | | - channel_internal_error/3, server_misbehaved/2, channels_terminated/1, |
18 | | - close/3, server_close/2, info/2, info_keys/0, info_keys/1, |
19 | | - register_blocked_handler/2, update_secret/2]). |
| 17 | + channel_internal_error/3, channel_closed/2, server_misbehaved/2, |
| 18 | + channels_terminated/1, close/3, server_close/2, info/2, info_keys/0, |
| 19 | + info_keys/1, register_blocked_handler/2, update_secret/2]). |
20 | 20 | -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, |
21 | 21 | handle_info/2]). |
22 | 22 |
|
|
32 | 32 | %% connection.block, connection.unblock handler |
33 | 33 | block_handler, |
34 | 34 | blocked_by = sets:new([{version, 2}]), |
35 | | - queue_types_published = sets:new([{version, 2}]), |
| 35 | + queue_types_published = #{}, |
36 | 36 | closing = false %% #closing{} | false |
37 | 37 | }). |
38 | 38 |
|
@@ -97,6 +97,9 @@ hard_error_in_channel(Pid, ChannelPid, Reason) -> |
97 | 97 | channel_internal_error(Pid, ChannelPid, Reason) -> |
98 | 98 | gen_server:cast(Pid, {channel_internal_error, ChannelPid, Reason}). |
99 | 99 |
|
| 100 | +channel_closed(Pid, TaggedWriter) -> |
| 101 | + gen_server:cast(Pid, {channel_closed, TaggedWriter}). |
| 102 | + |
100 | 103 | server_misbehaved(Pid, AmqpError) -> |
101 | 104 | gen_server:cast(Pid, {server_misbehaved, AmqpError}). |
102 | 105 |
|
@@ -223,10 +226,23 @@ handle_cast({conserve_resources, Source, Conserve}, |
223 | 226 | end, |
224 | 227 | State1 = State#state{blocked_by = BlockedBy1}, |
225 | 228 | maybe_block(State, State1); |
226 | | -handle_cast({channel_published_to_queue_type, _ChPid, QT}, |
| 229 | +handle_cast({channel_published_to_queue_type, ServerChPid, QT}, |
| 230 | + #state{queue_types_published = QTs} = State) -> |
| 231 | + %% ServerChPid is the server-side channel pid. We key by {direct, ServerChPid} |
| 232 | + %% so channel_closed can remove the entry using the tagged writer. |
| 233 | + Key = {direct, ServerChPid}, |
| 234 | + ChQTs = maps:get(Key, QTs, sets:new([{version, 2}])), |
| 235 | + State1 = State#state{queue_types_published = |
| 236 | + QTs#{Key => sets:add_element(QT, ChQTs)}}, |
| 237 | + maybe_block(State, State1); |
| 238 | +handle_cast({channel_closed, {direct, ServerChPid}}, |
227 | 239 | #state{queue_types_published = QTs} = State) -> |
228 | | - State1 = State#state{queue_types_published = sets:add_element(QT, QTs)}, |
229 | | - maybe_block(State, State1). |
| 240 | + State1 = State#state{queue_types_published = |
| 241 | + maps:remove({direct, ServerChPid}, QTs)}, |
| 242 | + maybe_block(State, State1); |
| 243 | +handle_cast({channel_closed, {network, _WriterPid}}, State) -> |
| 244 | + %% Network connections are handled by rabbit_reader, not here. |
| 245 | + {noreply, State}. |
230 | 246 |
|
231 | 247 | %% @private |
232 | 248 | handle_info({'DOWN', _, process, BlockHandler, Reason}, |
@@ -284,7 +300,9 @@ maybe_block(State0, State1) -> |
284 | 300 |
|
285 | 301 | should_block(#state{blocked_by = BlockedBy, queue_types_published = QTs}) -> |
286 | 302 | lists:any(fun ({disk, QT}) -> |
287 | | - sets:is_element(QT, QTs); |
| 303 | + maps:fold(fun(_, ChQTs, Acc) -> |
| 304 | + Acc orelse sets:is_element(QT, ChQTs) |
| 305 | + end, false, QTs); |
288 | 306 | (_Resource) -> |
289 | 307 | true |
290 | 308 | end, sets:to_list(BlockedBy)). |
|
0 commit comments