Coverage for /Users/eugene/Development/robotnikmq/robotnikmq/topic.py: 76%

21 statements  

« prev     ^ index     » next       coverage.py v7.3.4, created at 2023-12-26 19:13 -0500

1import json 

2from typing import Optional 

3 

4from pika.exceptions import AMQPError 

5from pika.exchange_type import ExchangeType 

6from tenacity import retry, retry_if_exception_type, wait_exponential 

7from typeguard import typechecked 

8 

9from robotnikmq.config import RobotnikConfig 

10from robotnikmq.core import Robotnik, Message 

11 

12 

13class Topic(Robotnik): 

14 """The Topic is one of two key elements of the Publish/Subscribe workflow with RobotnikMQ. 

15 Once configured, a topic is able to broadcast messages to any Subscribers on a given exchange 

16 and routing key combination. 

17 """ 

18 @typechecked 

19 def __init__( 

20 self, 

21 exchange: str, 

22 config: Optional[RobotnikConfig] = None, 

23 ): 

24 super().__init__(config=config) 

25 self.exchange = exchange 

26 self.channel.exchange_declare( 

27 exchange=self.exchange, exchange_type=ExchangeType.topic, auto_delete=True 

28 ) 

29 

30 @retry( 

31 retry=retry_if_exception_type((AMQPError, OSError)), 

32 wait=wait_exponential(multiplier=1, min=3, max=30), 

33 ) 

34 @typechecked 

35 def broadcast( 

36 self, 

37 msg: Message, 

38 routing_key: Optional[str] = None 

39 ) -> None: 

40 """Broadcasts a message with an optional routing key. 

41 

42 Args: 

43 msg (Message): The message to be broadcast. 

44 routing_key (Optional[str], optional): Routing key used to broadcast the message. 

45 Defaults to an empty string. 

46 on_msg_error (AMQPErrorCallback, optional): _description_. Defaults to None. 

47 """ 

48 msg = msg.with_routing_key(routing_key or msg.routing_key or "") 

49 self.log.info("Broadcasting message (routing-key: [{}]):\n{}", 

50 msg.routing_key, json.dumps(msg.to_dict(), indent=4)) 

51 self.channel.basic_publish( 

52 exchange=self.exchange, 

53 routing_key=msg.routing_key, 

54 body=json.dumps(msg.to_dict()), 

55 ) 

56 self.log.success("Broadcast:\n{}", json.dumps(msg.to_dict(), indent=4))