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

21 statements  

« prev     ^ index     » next       coverage.py v7.3.4, created at 2023-12-26 23:29 -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 reraise=True 

34 ) 

35 @typechecked 

36 def broadcast( 

37 self, 

38 msg: Message, 

39 routing_key: Optional[str] = None 

40 ) -> None: 

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

42 

43 Args: 

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

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

46 Defaults to an empty string. 

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

48 """ 

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

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

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

52 self.channel.basic_publish( 

53 exchange=self.exchange, 

54 routing_key=msg.routing_key, 

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

56 ) 

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