2828 code_change /3 ]).
2929-export ([messages_delayed /1 ]).
3030
31+ % % For testing, debugging and manual use
32+ -export ([refresh_config /0 ]).
33+
3134-import (rabbit_delayed_message_utils , [swap_delay_header /1 ]).
3235
3336-type t_reference () :: reference ().
4952-define (TABLE_NAME , append_to_atom (? MODULE , node ())).
5053-define (INDEX_TABLE_NAME , append_to_atom (? TABLE_NAME , " _index" )).
5154
52- -record (state , {timer }).
55+ -record (state , {timer ,
56+ stats_state }).
5357
5458-record (delay_key ,
5559 { timestamp , % % timestamp delay
@@ -104,6 +108,9 @@ messages_delayed(Exchange) ->
104108 Delays = mnesia :dirty_select (? TABLE_NAME , [{MatchHead , [], ['$_' ]}]),
105109 length (Delays ).
106110
111+ refresh_config () ->
112+ gen_server :call (? MODULE , refresh_config ).
113+
107114% %--------------------------------------------------------------------
108115
109116init ([]) ->
@@ -120,11 +127,14 @@ handle_call({delay_message, Exchange, Delivery, Delay},
120127 State
121128 end ,
122129 {reply , Reply , State2 };
130+ handle_call (refresh_config , _From , State ) ->
131+ {reply , ok , refresh_config (State )};
123132handle_call (_Req , _From , State ) ->
124133 {reply , unknown_request , State }.
125134
126135handle_cast (go , State ) ->
127- {noreply , State # state {timer = maybe_delay_first ()}};
136+ State2 = refresh_config (State ),
137+ {noreply , State2 # state {timer = maybe_delay_first ()}};
128138handle_cast (_C , State ) ->
129139 {noreply , State }.
130140
@@ -133,7 +143,7 @@ handle_info({timeout, _TimerRef, {deliver, Key}}, State) ->
133143 [] ->
134144 ok ;
135145 Deliveries ->
136- route (Key , Deliveries ),
146+ route (Key , Deliveries , State ),
137147 mnesia :dirty_delete (? TABLE_NAME , Key ),
138148 mnesia :dirty_delete (? INDEX_TABLE_NAME , Key )
139149 end ,
@@ -160,12 +170,14 @@ maybe_delay_first() ->
160170 not_set
161171 end .
162172
163- route (# delay_key {exchange = Ex }, Deliveries ) ->
173+ route (# delay_key {exchange = Ex }, Deliveries , State ) ->
174+ ExName = Ex # exchange .name ,
164175 lists :map (fun (# delay_entry {delivery = D }) ->
165176 D2 = swap_delay_header (D ),
166177 Dests = rabbit_exchange :route (Ex , D2 ),
167178 Qs = rabbit_amqqueue :lookup (Dests ),
168- rabbit_amqqueue :deliver (Qs , D2 )
179+ rabbit_amqqueue :deliver (Qs , D2 ),
180+ bump_routed_stats (ExName , Qs , State )
169181 end , Deliveries ).
170182
171183internal_delay_message (CurrTimer , Exchange , Delivery , Delay ) ->
@@ -260,3 +272,45 @@ recover_exchange_and_bindings(#exchange{name = XName} = X) ->
260272 " recovered bindings for ~s " ,
261273 [rabbit_misc :rs (XName )])
262274 end ).
275+
276+ % % These metrics are normally bumped from a channel process via which
277+ % % the publish actually happened. In the special case of delayed
278+ % % message delivery, the singleton delayed_message gen_server does
279+ % % this.
280+ % %
281+ % % Difference from delivering from a channel:
282+ % %
283+ % % The channel process keeps track of the state and monitors each
284+ % % queue it routed to. When the channel is notified of a queue DOWN,
285+ % % it marks all core metrics for that channel + queue as deleted.
286+ % % Monitoring all queues would be overkill for the delayed message
287+ % % gen_server, so this delete marking does not happen in this
288+ % % case. Still `rabbit_core_metrics_gc' will periodically scan all the
289+ % % core metrics and eventually delete entries for non-existing queues
290+ % % so there won't be any metrics leak. `rabbit_core_metrics_gc' will
291+ % % also delete the entries when this process is not alive ie when the
292+ % % plugin is disabled.
293+ bump_routed_stats (ExName , Qs , State ) ->
294+ rabbit_global_counters :messages_routed (amqp091 , length (Qs )),
295+ case rabbit_event :stats_level (State , # state .stats_state ) of
296+ fine ->
297+ [begin
298+ QName = amqqueue :get_name (Q ),
299+ % % Channel PID is just an identifier in the metrics
300+ % % DB. However core metrics GC will delete entries
301+ % % with a not-alive PID, and by the time the delayed
302+ % % message gets delivered the original channel
303+ % % process might be long gone, hence we need a live
304+ % % PID in the key.
305+ FakeChannelId = self (),
306+ Key = {FakeChannelId , {QName , ExName }},
307+ rabbit_core_metrics :channel_stats (queue_exchange_stats , publish , Key , 1 )
308+ end
309+ || Q <- Qs ],
310+ ok ;
311+ _ ->
312+ ok
313+ end .
314+
315+ refresh_config (State ) ->
316+ rabbit_event :init_stats_timer (State , # state .stats_state ).
0 commit comments