@@ -126,7 +126,8 @@ cluster_size_1_tests() ->
126126 topic_alias_disallowed_retained_message ,
127127 extended_auth ,
128128 headers_exchange ,
129- consistent_hash_exchange
129+ consistent_hash_exchange ,
130+ consumer_timeout_quorum_queue
130131 ].
131132
132133cluster_size_3_tests () ->
@@ -2158,6 +2159,58 @@ consistent_hash_exchange(Config) ->
21582159 [# 'queue.delete_ok' {} = amqp_channel :call (Ch , # 'queue.delete' {queue = Q }) || Q <- Qs ],
21592160 ok = rabbit_ct_client_helpers :close_channels_and_connection (Config , 0 ).
21602161
2162+ % % Test that consumer timeout on a quorum queue terminates the MQTT connection.
2163+ % % Consumer timeouts are only supported for quorum queues.
2164+ % %
2165+ % % We use {auto_ack, never} to prevent emqtt from automatically sending PUBACK,
2166+ % % which allows the consumer timeout to trigger.
2167+ consumer_timeout_quorum_queue (Config ) ->
2168+ Topic = atom_to_binary (? FUNCTION_NAME ),
2169+ PolicyName = <<" consumer-timeout-policy" >>,
2170+
2171+ ok = rpc (Config , application , set_env , [? APP , durable_queue_type , quorum ]),
2172+ % % Set a short consumer timeout policy for quorum queues
2173+ ok = rabbit_ct_broker_helpers :set_policy (
2174+ Config , 0 , PolicyName , <<" .*" >>, <<" quorum_queues" >>,
2175+ [{<<" consumer-timeout" >>, 1000 }]),
2176+
2177+ % % Use two clients: one for publishing (normal auto_ack), one for subscribing (auto_ack=never)
2178+ Pub = connect (<<" publisher" >>, Config ),
2179+ Sub = connect (? FUNCTION_NAME , Config ,
2180+ non_clean_sess_opts () ++ [{auto_ack , never }]),
2181+ {ok , _ , [1 ]} = emqtt :subscribe (Sub , Topic , qos1 ),
2182+
2183+ % % Publish a message from the publisher client
2184+ {ok , _ } = emqtt :publish (Pub , Topic , <<" test message" >>, [{qos , 1 }]),
2185+
2186+ % % Receive the message on subscriber but do NOT acknowledge it (auto_ack=never)
2187+ receive
2188+ {publish , #{client_pid := Sub ,
2189+ topic := Topic ,
2190+ payload := <<" test message" >>}} ->
2191+ ok
2192+ after 5000 ->
2193+ ct :fail (" did not receive message" )
2194+ end ,
2195+
2196+ ok = rpc (Config , application , unset_env , [? APP , durable_queue_type ]),
2197+
2198+ % % Trap exits so we receive EXIT message instead of crashing when Sub exits
2199+ process_flag (trap_exit , true ),
2200+
2201+ % % The subscriber connection should be terminated due to consumer timeout
2202+ % % Wait for the consumer timeout (1s) plus some margin
2203+ util :await_exit (Sub ),
2204+
2205+ process_flag (trap_exit , false ),
2206+
2207+ % % Cleanup
2208+ ok = emqtt :disconnect (Pub ),
2209+ ok = rabbit_ct_broker_helpers :clear_policy (Config , 0 , PolicyName ),
2210+ % % Clean up the session by connecting with clean_start
2211+ C2 = connect (? FUNCTION_NAME , Config , [{clean_start , true }]),
2212+ ok = emqtt :disconnect (C2 ).
2213+
21612214% % -------------------------------------------------------------------
21622215% % Helpers
21632216% % -------------------------------------------------------------------
0 commit comments