@@ -53,6 +53,7 @@ def __init__( # noqa: WPS211
5353 routing_key : str = "#" ,
5454 exchange_type : ExchangeType = ExchangeType .TOPIC ,
5555 max_priority : Optional [int ] = None ,
56+ delayed_message_exchange_plugin : bool = False ,
5657 ** connection_kwargs : Any ,
5758 ) -> None :
5859 """
@@ -79,6 +80,8 @@ def __init__( # noqa: WPS211
7980 :param exchange_type: type of the exchange.
8081 Used only if `declare_exchange` is True.
8182 :param max_priority: maximum priority value for messages.
83+ :param delayed_message_exchange_plugin: turn on or disable
84+ delayed-message-exchange rabbitmq plugin.
8285 :param connection_kwargs: additional keyword arguments,
8386 for connect_robust method of aio-pika.
8487 """
@@ -95,6 +98,7 @@ def __init__( # noqa: WPS211
9598 self ._queue_name = queue_name
9699 self ._routing_key = routing_key
97100 self ._max_priority = max_priority
101+ self ._delayed_message_exchange_plugin = delayed_message_exchange_plugin
98102
99103 self ._dead_letter_queue_name = f"{ queue_name } .dead_letter"
100104 if dead_letter_queue_name :
@@ -104,6 +108,8 @@ def __init__( # noqa: WPS211
104108 if delay_queue_name :
105109 self ._delay_queue_name = delay_queue_name
106110
111+ self ._delay_plugin_exchange_name = f"{ exchange_name } .plugin_delay"
112+
107113 self .read_conn : Optional [AbstractRobustConnection ] = None
108114 self .write_conn : Optional [AbstractRobustConnection ] = None
109115 self .write_channel : Optional [AbstractChannel ] = None
@@ -132,9 +138,31 @@ async def startup(self) -> None: # noqa: WPS217
132138 self ._exchange_name ,
133139 type = self ._exchange_type ,
134140 )
141+
142+ if self ._delayed_message_exchange_plugin :
143+ await self .write_channel .declare_exchange (
144+ self ._delay_plugin_exchange_name ,
145+ type = ExchangeType .X_DELAYED_MESSAGE ,
146+ arguments = {
147+ "x-delayed-type" : "direct" ,
148+ },
149+ )
150+
135151 if self ._declare_queues :
136152 await self .declare_queues (self .write_channel )
137153
154+ async def shutdown (self ) -> None :
155+ """Close all connections on shutdown."""
156+ await super ().shutdown ()
157+ if self .write_channel :
158+ await self .write_channel .close ()
159+ if self .read_channel :
160+ await self .read_channel .close ()
161+ if self .write_conn :
162+ await self .write_conn .close ()
163+ if self .read_conn :
164+ await self .read_conn .close ()
165+
138166 async def declare_queues (
139167 self ,
140168 channel : AbstractChannel ,
@@ -163,14 +191,24 @@ async def declare_queues(
163191 self ._queue_name ,
164192 arguments = args ,
165193 )
166- await channel .declare_queue (
167- self ._delay_queue_name ,
168- arguments = {
169- "x-dead-letter-exchange" : "" ,
170- "x-dead-letter-routing-key" : self ._queue_name ,
171- },
194+ if self ._delayed_message_exchange_plugin :
195+ await queue .bind (
196+ exchange = self ._delay_plugin_exchange_name ,
197+ routing_key = self ._routing_key ,
198+ )
199+ else :
200+ await channel .declare_queue (
201+ self ._delay_queue_name ,
202+ arguments = {
203+ "x-dead-letter-exchange" : "" ,
204+ "x-dead-letter-routing-key" : self ._queue_name ,
205+ },
206+ )
207+
208+ await queue .bind (
209+ exchange = self ._exchange_name ,
210+ routing_key = self ._routing_key ,
172211 )
173- await queue .bind (exchange = self ._exchange_name , routing_key = self ._routing_key )
174212 return queue
175213
176214 async def kick (self , message : BrokerMessage ) -> None :
@@ -189,30 +227,47 @@ async def kick(self, message: BrokerMessage) -> None:
189227 """
190228 if self .write_channel is None :
191229 raise ValueError ("Please run startup before kicking." )
192- priority = parse_val ( int , message . labels . get ( "priority" ))
193- rmq_msg = Message (
194- body = message .message ,
195- headers = {
230+
231+ message_base_params : dict [ str , Any ] = {
232+ " body" : message .message ,
233+ " headers" : {
196234 "task_id" : message .task_id ,
197235 "task_name" : message .task_name ,
198236 ** message .labels ,
199237 },
200- delivery_mode = DeliveryMode .PERSISTENT ,
201- priority = priority ,
238+ "delivery_mode" : DeliveryMode .PERSISTENT ,
239+ }
240+
241+ message_base_params ["priority" ] = parse_val (
242+ int ,
243+ message .labels .get ("priority" ),
202244 )
203- delay = parse_val (int , message .labels .get ("delay" ))
245+
246+ delay : Optional [int ] = parse_val (int , message .labels .get ("delay" ))
247+ rmq_message : Message = Message (** message_base_params )
248+
204249 if delay is None :
205250 exchange = await self .write_channel .get_exchange (
206251 self ._exchange_name ,
207252 ensure = False ,
208253 )
209- await exchange .publish (rmq_msg , routing_key = message .task_name )
254+ await exchange .publish (rmq_message , routing_key = message .task_name )
210255 else :
211- rmq_msg .expiration = timedelta (seconds = delay )
212- await self .write_channel .default_exchange .publish (
213- rmq_msg ,
214- routing_key = self ._delay_queue_name ,
215- )
256+ if self ._delayed_message_exchange_plugin :
257+ rmq_message .headers ["x-delay" ] = delay * 1000
258+ exchange = await self .write_channel .get_exchange (
259+ self ._delay_plugin_exchange_name ,
260+ )
261+ await exchange .publish (
262+ rmq_message ,
263+ routing_key = self ._routing_key ,
264+ )
265+ else :
266+ rmq_message .expiration = timedelta (seconds = delay )
267+ await self .write_channel .default_exchange .publish (
268+ rmq_message ,
269+ routing_key = self ._delay_queue_name ,
270+ )
216271
217272 async def listen (self ) -> AsyncGenerator [bytes , None ]:
218273 """
@@ -232,15 +287,3 @@ async def listen(self) -> AsyncGenerator[bytes, None]:
232287 async for message in iterator :
233288 async with message .process ():
234289 yield message .body
235-
236- async def shutdown (self ) -> None :
237- """Close all connections on shutdown."""
238- await super ().shutdown ()
239- if self .write_channel :
240- await self .write_channel .close ()
241- if self .read_channel :
242- await self .read_channel .close ()
243- if self .write_conn :
244- await self .write_conn .close ()
245- if self .read_conn :
246- await self .read_conn .close ()
0 commit comments