@@ -22,7 +22,7 @@ defmodule RabbitMQMessageDeduplication.Queue do
2222
2323 """
2424
25- import Record , only: [ defrecord: 2 , defrecord: 3 , defrecordp: 2 , extract: 2 ]
25+ import Record , only: [ defrecord: 2 , defrecord: 3 , extract: 2 ]
2626
2727 require RabbitMQMessageDeduplication.Cache
2828 require RabbitMQMessageDeduplication.Common
@@ -55,7 +55,7 @@ defmodule RabbitMQMessageDeduplication.Queue do
5555 :P_basic , from_lib: "rabbit_common/include/rabbit_framing.hrl" )
5656
5757 defrecord :dqack , [ :tag , :header ]
58- defrecord :dqstate , [ :queue , :queue_state , : dedup_enabled]
58+ defrecord :dqstate , [ :queue , :queue_state , dedup_enabled: false ]
5959
6060 # The passthrough macros call the underlying backing queue functions
6161 # The suffixes indicate the arity of the return values
@@ -149,7 +149,7 @@ defmodule RabbitMQMessageDeduplication.Queue do
149149
150150 @ impl :rabbit_backing_queue
151151 def init ( queue , recovery , callback ) do
152- state = maybe_enable_dedup_queue ( dqstate ( queue: queue ) )
152+ state = maybe_toggle_dedup_queue ( dqstate ( queue: queue ) )
153153
154154 passthrough1 ( state ) do
155155 init ( queue , recovery , callback )
@@ -164,10 +164,7 @@ defmodule RabbitMQMessageDeduplication.Queue do
164164 @ impl :rabbit_backing_queue
165165 def delete_and_terminate ( any , state = dqstate ( queue: queue , queue_state: qs ) ) do
166166 if dedup_queue? ( state ) do
167- queue
168- |> AMQQueue . get_name ( )
169- |> Common . cache_name ( )
170- |> CacheManager . destroy ( )
167+ :ok = delete_cache ( queue )
171168 end
172169
173170 passthrough1 ( state ) do
@@ -468,28 +465,19 @@ defmodule RabbitMQMessageDeduplication.Queue do
468465
469466 # Utility functions
470467
471- # Set the state according to whether the queue is a deduplication one or not
472- def maybe_enable_dedup_queue ( state = dqstate ( queue: queue , queue_state: qs ) ) do
473- if dedup_queue? ( state ) do
474- :ok = init_cache ( queue )
475- dqstate ( queue: queue , queue_state: qs , dedup_enabled: true )
476- else
477- dqstate ( queue: queue , queue_state: qs , dedup_enabled: :undefined )
468+ # Enable/disable queue-level deduplication
469+ def maybe_toggle_dedup_queue ( state = dqstate ( queue: queue , queue_state: qs ) ) do
470+ cond do
471+ enable_dedup_queue? ( state ) ->
472+ :ok = init_cache ( queue )
473+ dqstate ( queue: queue , queue_state: qs , dedup_enabled: true )
474+ disable_dedup_queue? ( state ) ->
475+ :ok = delete_cache ( queue )
476+ dqstate ( queue: queue , queue_state: qs , dedup_enabled: false )
477+ true -> dqstate ( queue: queue , queue_state: qs , dedup_enabled: false )
478478 end
479479 end
480480
481- # Check if it's a deduplication enabled queue
482- defp dedup_queue? ( dqstate ( dedup_enabled: val ) ) when is_boolean ( val ) , do: val
483- defp dedup_queue? ( dqstate ( queue: queue ) ) do
484- args = AMQQueue . get_arguments ( queue )
485- pols = case AMQQueue . get_policy ( queue ) do
486- :undefined -> [ ]
487- policy -> policy [ :definition ]
488- end
489-
490- Common . rabbit_argument ( args ++ pols , "x-message-deduplication" , default: false )
491- end
492-
493481 # Initialize the deduplication cache
494482 defp init_cache ( queue ) do
495483 cache = queue |> AMQQueue . get_name ( ) |> Common . cache_name ( )
@@ -509,6 +497,15 @@ defmodule RabbitMQMessageDeduplication.Queue do
509497 end
510498 end
511499
500+ # Remove the cache and all its content
501+ defp delete_cache ( queue ) do
502+ cache = queue |> AMQQueue . get_name ( ) |> Common . cache_name ( )
503+
504+ RabbitLog . debug ( "Deleting queue deduplication cache ~s~n" , [ cache ] )
505+
506+ CacheManager . destroy ( cache )
507+ end
508+
512509 # Returns true if the message is a duplicate.
513510 defp duplicate? ( queue , message = basic_message ( ) ) do
514511 name = AMQQueue . get_name ( queue )
@@ -559,4 +556,30 @@ defmodule RabbitMQMessageDeduplication.Queue do
559556 :exit , { :noproc , { GenServer , :call , [ ^ cache | _ ] } } -> [ ]
560557 end
561558 end
559+
560+ # True if `x-message-deduplication` is present within queue arguments or policy
561+ defp dedup_arg? ( queue ) do
562+ queue_policy ( queue )
563+ ++ AMQQueue . get_arguments ( queue )
564+ |> Common . rabbit_argument ( "x-message-deduplication" , default: false )
565+ end
566+
567+ # Return the list of policy arguments assigned to the queue
568+ defp queue_policy ( queue ) do
569+ case AMQQueue . get_policy ( queue ) do
570+ :undefined -> [ ]
571+ policy -> policy [ :definition ]
572+ end
573+ end
574+
575+ # True if it's an active deduplication queue
576+ defp dedup_queue? ( dqstate ( dedup_enabled: val ) ) , do: val
577+
578+ # True if deduplication should be enabled for the queue
579+ defp enable_dedup_queue? ( dqstate ( dedup_enabled: true ) ) , do: false
580+ defp enable_dedup_queue? ( dqstate ( queue: q , dedup_enabled: false ) ) , do: dedup_arg? ( q )
581+
582+ # True if deduplication should be disabled for the queue
583+ defp disable_dedup_queue? ( dqstate ( dedup_enabled: false ) ) , do: false
584+ defp disable_dedup_queue? ( dqstate ( queue: q , dedup_enabled: true ) ) , do: not dedup_arg? ( q )
562585end
0 commit comments