@@ -1610,19 +1610,36 @@ handle_frame_post_auth(Transport,
1610
1610
case Consumers of
1611
1611
#{SubscriptionId := Consumer } ->
1612
1612
# consumer {credit = AvailableCredit } = Consumer ,
1613
-
1614
- {{segment , Segment1 }, {credit , Credit1 }} =
1615
- send_chunks (Transport ,
1616
- Consumer ,
1617
- AvailableCredit + Credit ,
1618
- SendFileOct ),
1619
-
1620
- Consumer1 = Consumer # consumer {segment = Segment1 , credit = Credit1 },
1621
- {Connection ,
1622
- State # stream_connection_state {consumers =
1623
- Consumers #{SubscriptionId =>
1624
- Consumer1 }},
1625
- Rest };
1613
+ case send_chunks (Transport ,
1614
+ Consumer ,
1615
+ AvailableCredit + Credit ,
1616
+ SendFileOct )
1617
+ of
1618
+ {error , closed } ->
1619
+ rabbit_log :warning (" Reader for subscription ~p has been closed, removing "
1620
+ " subscription" ,
1621
+ [SubscriptionId ]),
1622
+ {Connection1 , State1 } =
1623
+ remove_subscription (SubscriptionId , Connection , State ),
1624
+ Frame =
1625
+ <<? RESPONSE :1 ,
1626
+ ? COMMAND_CREDIT :15 ,
1627
+ ? VERSION_1 :16 ,
1628
+ ? RESPONSE_CODE_SUBSCRIPTION_ID_DOES_NOT_EXIST :16 ,
1629
+ SubscriptionId :8 >>,
1630
+ FrameSize = byte_size (Frame ),
1631
+ Transport :send (S , [<<FrameSize :32 >>, Frame ]),
1632
+ {Connection1 , State1 , Rest };
1633
+ {{segment , Segment1 }, {credit , Credit1 }} ->
1634
+ Consumer1 =
1635
+ Consumer # consumer {segment = Segment1 , credit = Credit1 },
1636
+ {Connection ,
1637
+ State # stream_connection_state {consumers =
1638
+ Consumers #{SubscriptionId
1639
+ =>
1640
+ Consumer1 }},
1641
+ Rest }
1642
+ end ;
1626
1643
_ ->
1627
1644
rabbit_log :warning (" Giving credit to unknown subscription: ~p " ,
1628
1645
[SubscriptionId ]),
@@ -1744,36 +1761,13 @@ handle_frame_post_auth(Transport,
1744
1761
? RESPONSE_CODE_SUBSCRIPTION_ID_DOES_NOT_EXIST ),
1745
1762
{Connection , State , Rest };
1746
1763
true ->
1747
- #{SubscriptionId := Consumer } = Consumers ,
1748
- Stream = Consumer # consumer .stream ,
1749
- #{Stream := SubscriptionsForThisStream } = StreamSubscriptions ,
1750
- SubscriptionsForThisStream1 =
1751
- lists :delete (SubscriptionId , SubscriptionsForThisStream ),
1752
- StreamSubscriptions1 =
1753
- case length (SubscriptionsForThisStream1 ) of
1754
- 0 ->
1755
- % no more subscription for this stream
1756
- maps :remove (Stream , StreamSubscriptions );
1757
- _ ->
1758
- StreamSubscriptions #{Stream =>
1759
- SubscriptionsForThisStream1 }
1760
- end ,
1761
- Connection1 =
1762
- Connection # stream_connection {stream_subscriptions =
1763
- StreamSubscriptions1 },
1764
- Consumers1 = maps :remove (SubscriptionId , Consumers ),
1765
- Connection2 =
1766
- maybe_clean_connection_from_stream (Stream , Connection1 ),
1767
- rabbit_stream_metrics :consumer_cancelled (self (),
1768
- stream_r (Stream ,
1769
- Connection2 ),
1770
- SubscriptionId ),
1764
+ {Connection1 , State1 } =
1765
+ remove_subscription (SubscriptionId , Connection , State ),
1771
1766
response_ok (Transport ,
1772
1767
Connection ,
1773
- ? COMMAND_SUBSCRIBE ,
1768
+ ? COMMAND_UNSUBSCRIBE ,
1774
1769
CorrelationId ),
1775
- {Connection2 , State # stream_connection_state {consumers = Consumers1 },
1776
- Rest }
1770
+ {Connection1 , State1 , Rest }
1777
1771
end ;
1778
1772
handle_frame_post_auth (Transport ,
1779
1773
# stream_connection {virtual_host = VirtualHost ,
@@ -2344,6 +2338,34 @@ lookup_leader(Stream,
2344
2338
lookup_leader_from_manager (VirtualHost , Stream ) ->
2345
2339
rabbit_stream_manager :lookup_leader (VirtualHost , Stream ).
2346
2340
2341
+ remove_subscription (SubscriptionId ,
2342
+ # stream_connection {stream_subscriptions =
2343
+ StreamSubscriptions } =
2344
+ Connection ,
2345
+ # stream_connection_state {consumers = Consumers } = State ) ->
2346
+ #{SubscriptionId := Consumer } = Consumers ,
2347
+ Stream = Consumer # consumer .stream ,
2348
+ #{Stream := SubscriptionsForThisStream } = StreamSubscriptions ,
2349
+ SubscriptionsForThisStream1 =
2350
+ lists :delete (SubscriptionId , SubscriptionsForThisStream ),
2351
+ StreamSubscriptions1 =
2352
+ case length (SubscriptionsForThisStream1 ) of
2353
+ 0 ->
2354
+ % no more subscription for this stream
2355
+ maps :remove (Stream , StreamSubscriptions );
2356
+ _ ->
2357
+ StreamSubscriptions #{Stream => SubscriptionsForThisStream1 }
2358
+ end ,
2359
+ Connection1 =
2360
+ Connection # stream_connection {stream_subscriptions =
2361
+ StreamSubscriptions1 },
2362
+ Consumers1 = maps :remove (SubscriptionId , Consumers ),
2363
+ Connection2 = maybe_clean_connection_from_stream (Stream , Connection1 ),
2364
+ rabbit_stream_metrics :consumer_cancelled (self (),
2365
+ stream_r (Stream , Connection2 ),
2366
+ SubscriptionId ),
2367
+ {Connection2 , State # stream_connection_state {consumers = Consumers1 }}.
2368
+
2347
2369
maybe_clean_connection_from_stream (Stream ,
2348
2370
# stream_connection {stream_leaders =
2349
2371
Leaders } =
@@ -2491,6 +2513,8 @@ send_chunks(Transport,
2491
2513
of
2492
2514
{ok , Segment1 } ->
2493
2515
send_chunks (Transport , State , Segment1 , Credit - 1 , true , Counter );
2516
+ {error , closed } ->
2517
+ {error , closed };
2494
2518
{end_of_stream , Segment1 } ->
2495
2519
case Retry of
2496
2520
true ->
0 commit comments