h-message-bus 0.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ from .adapters.nats_publisher_adapter import NatsPublisherAdapter
2
+ from .adapters.nats_subscriber_adapter import NatsSubscriberAdapter
3
+ from .application.message_processor import MessageProcessor
4
+ from .infrastructure.nats_client_repository import NatsClientRepository
5
+ from .infrastructure.nats_config import NatsConfig
6
+ from .domain.hai_message import HaiMessage
7
+
8
+
9
+ __all__ = ['NatsConfig', 'HaiMessage', 'MessageProcessor', 'NatsClientRepository', 'NatsSubscriberAdapter', 'NatsPublisherAdapter']
10
+
11
+
File without changes
@@ -0,0 +1,36 @@
1
+ from nats.aio.msg import Msg as NatsMsg
2
+
3
+ from src.h_message_bus.application.message_processor import MessageProcessor
4
+ from src.h_message_bus.domain.hai_message import HaiMessage
5
+
6
+
7
+ class NatsMessageAdapter:
8
+ """
9
+ Adapter class to handle incoming NATS messages and process them using
10
+ a message processor.
11
+
12
+ The class serves as a bridge between NATS messaging and a domain-specific
13
+ message processor. It listens for incoming messages, converts them into
14
+ the appropriate domain object, processes them with the provided message
15
+ processor, and optionally sends a response if required.
16
+
17
+ :ivar processor: Instance of the message processor used to process domain
18
+ messages.
19
+ :type processor: MessageProcessor
20
+ """
21
+ def __init__(self, message_processor: MessageProcessor):
22
+ self.processor = message_processor
23
+
24
+ async def handle_nats_message(self, msg: NatsMsg) -> None:
25
+ """Handle incoming NATS message."""
26
+ try:
27
+ domain_message = HaiMessage.from_json(msg.data.decode())
28
+
29
+ response = await self.processor.process(domain_message)
30
+
31
+ # If there's a reply subject and a response, send it back
32
+ if msg.reply and response:
33
+ await msg.respond(response.to_json().encode())
34
+
35
+ except Exception as e:
36
+ print(f"Error processing message: {e}")
@@ -0,0 +1,46 @@
1
+ from typing import Optional
2
+
3
+ from src.h_message_bus.application.message_publisher import MessagePublisher
4
+ from src.h_message_bus.domain.hai_message import HaiMessage
5
+ from src.h_message_bus.infrastructure.nats_client_repository import NatsClientRepository
6
+
7
+
8
+ class NatsPublisherAdapter(MessagePublisher):
9
+ """
10
+ Adapter for publishing and requesting messages using a NATS client.
11
+
12
+ This class interacts with a NATS client to publish messages to specified
13
+ topics or send requests and wait for responses. It is designed to work
14
+ with the `HaiMessage` format for message objects. The adapter encapsulates
15
+ underlying communication details and provides an easy-to-use interface
16
+ for message-based interactions.
17
+
18
+ :ivar nats_client: Instance of NatsClientRepository used for interacting
19
+ with the NATS system.
20
+ :type nats_client: NatsClientRepository
21
+ """
22
+
23
+ def __init__(self, nats_client: NatsClientRepository):
24
+ self.nats_client = nats_client
25
+
26
+ async def publish(self, message: HaiMessage) -> None:
27
+ """Publish a message to NATS."""
28
+ await self.nats_client.publish(
29
+ message.topic,
30
+ message.to_json().encode()
31
+ )
32
+
33
+ async def request(self, message: HaiMessage, timeout: float = 2.0) -> Optional[HaiMessage]:
34
+ """Send a request and wait for a response."""
35
+ try:
36
+ response = await self.nats_client.request(
37
+ message.topic,
38
+ message.to_json().encode(),
39
+ timeout=timeout
40
+ )
41
+ if response:
42
+ return HaiMessage.from_json(response.decode())
43
+ return None
44
+ except Exception as e:
45
+ print(f"Request failed: {e}")
46
+ return None
@@ -0,0 +1,53 @@
1
+ from typing import Dict
2
+
3
+ from src.h_message_bus.adapters.nats_message_adapter import NatsMessageAdapter
4
+ from src.h_message_bus.application.message_processor import MessageProcessor
5
+ from src.h_message_bus.application.message_subcriber import MessageSubscriber
6
+ from src.h_message_bus.infrastructure.nats_client_repository import NatsClientRepository
7
+
8
+
9
+ class NatsSubscriberAdapter(MessageSubscriber):
10
+ """
11
+ Handles subscription to message topics using a NATS client.
12
+
13
+ The class provides methods to subscribe to specific topics with a
14
+ message processor and to manage subscriptions by unsubscribing from
15
+ all topics. It works with a NATS client repository and acts as a
16
+ bridge between the messaging system and the application.
17
+
18
+ :ivar nats_client: The NATS client repository used for managing
19
+ subscriptions.
20
+ :type nats_client: NatsClientRepository
21
+ :ivar subscriptions: A list of active subscription objects.
22
+ :type subscriptions: list
23
+ :ivar adapters: A dictionary mapping topic names to their respective
24
+ message adapters.
25
+ :type adapters: Dict[str, NatsMessageAdapter]
26
+ """
27
+
28
+ def __init__(self, nats_client: NatsClientRepository):
29
+ self.nats_client = nats_client
30
+ self.subscriptions = []
31
+ self.adapters: Dict[str, NatsMessageAdapter] = {}
32
+
33
+ async def subscribe(self, topic: str, processor: MessageProcessor) -> None:
34
+ """Subscribe to a topic with a message handler."""
35
+ # Create an adapter for this use case
36
+ message_adapter = NatsMessageAdapter(processor)
37
+ self.adapters[topic] = message_adapter
38
+
39
+ # Subscribe to the topic
40
+ subscription = await self.nats_client.subscribe(
41
+ topic,
42
+ callback=message_adapter.handle_nats_message
43
+ )
44
+
45
+ self.subscriptions.append(subscription)
46
+
47
+ async def unsubscribe_all(self) -> None:
48
+ """Unsubscribe from all subscriptions."""
49
+ for subscription in self.subscriptions:
50
+ await subscription.unsubscribe()
51
+
52
+ self.subscriptions = []
53
+ self.adapters = {}
File without changes
@@ -0,0 +1,21 @@
1
+ from abc import abstractmethod, ABC
2
+ from typing import Optional
3
+
4
+ from src.h_message_bus.domain.hai_message import HaiMessage
5
+
6
+
7
+ class MessageProcessor(ABC):
8
+ """
9
+ Defines an abstract base class for processing messages.
10
+
11
+ This class serves as a blueprint for creating message processing
12
+ implementations. It enforces a concrete implementation of the
13
+ 'process' method, which is expected to handle a given message
14
+ and optionally return a response. The specific logic of
15
+ processing must be defined in derived subclasses.
16
+ """
17
+
18
+ @abstractmethod
19
+ async def process(self, message: HaiMessage) -> Optional[HaiMessage]:
20
+ """Process a message and optionally return a response."""
21
+ pass
@@ -0,0 +1,25 @@
1
+ from abc import abstractmethod, ABC
2
+ from typing import Optional
3
+
4
+ from src.h_message_bus.domain.hai_message import HaiMessage
5
+
6
+
7
+ class MessagePublisher(ABC):
8
+ """
9
+ Represents an abstract base class for a message publishing mechanism.
10
+
11
+ This class serves as a template for creating message publishing systems
12
+ that can either publish messages asynchronously or handle request-response
13
+ patterns with optional timeouts. Subclasses must implement the abstract
14
+ methods to provide specific functionality.
15
+ """
16
+
17
+ @abstractmethod
18
+ async def publish(self, message: HaiMessage) -> None:
19
+ """Publish a message."""
20
+ pass
21
+
22
+ @abstractmethod
23
+ async def request(self, message: HaiMessage, timeout: float) -> Optional[HaiMessage]:
24
+ """Send a request and wait for response."""
25
+ pass
@@ -0,0 +1,24 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Callable
3
+
4
+
5
+ class MessageSubscriber(ABC):
6
+ """
7
+ Abstract base class representing a message subscriber.
8
+
9
+ This class defines the contract for subscribing to and unsubscribing from
10
+ message topics. Subclasses are required to implement the methods for
11
+ subscribing to topics with message handlers and unsubscribing from all
12
+ active subscriptions.
13
+
14
+ """
15
+
16
+ @abstractmethod
17
+ async def subscribe(self, topic: str, handler: Callable) -> None:
18
+ """Subscribe to a topic with a message handler."""
19
+ pass
20
+
21
+ @abstractmethod
22
+ async def unsubscribe_all(self) -> None:
23
+ """Unsubscribe from all subscriptions."""
24
+ pass
File without changes
@@ -0,0 +1,65 @@
1
+ import json
2
+ import uuid
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from typing import Dict, Any
6
+
7
+
8
+ @dataclass
9
+ class HaiMessage:
10
+ """
11
+ Represents a domain message with metadata and payload.
12
+
13
+ This class is used for handling messages with a specific topic and payload,
14
+ along with metadata such as an identifier and a timestamp. It provides
15
+ functionality for creation, serialization to JSON, and deserialization from JSON.
16
+
17
+ :ivar id: Unique identifier for the message.
18
+ :type id: str
19
+ :ivar topic: The topic associated with the message.
20
+ :type topic: str
21
+ :ivar payload: The payload of the message, represented as a dictionary.
22
+ :type payload: Dict[Any, Any]
23
+ :ivar timestamp: The timestamp indicating when the message was created.
24
+ :type timestamp: str
25
+ """
26
+ id: str
27
+ topic: str
28
+ payload: Dict[Any, Any]
29
+ timestamp: str = None
30
+
31
+ def __post_init__(self):
32
+ if not self.id:
33
+ self.id = str(uuid.uuid4())
34
+ if not self.timestamp:
35
+ self.timestamp = datetime.utcnow().isoformat()
36
+
37
+ @classmethod
38
+ def create(cls, topic: str, payload: Dict[Any, Any]) -> 'HaiMessage':
39
+ """Factory method to create a new domain message."""
40
+ return cls(
41
+ id=str(uuid.uuid4()),
42
+ topic=topic,
43
+ payload=payload,
44
+ timestamp=datetime.utcnow().isoformat()
45
+ )
46
+
47
+ def to_json(self) -> str:
48
+ """Convert message to JSON string."""
49
+ return json.dumps({
50
+ "id": self.id,
51
+ "topic": self.topic,
52
+ "payload": self.payload,
53
+ "timestamp": self.timestamp
54
+ })
55
+
56
+ @classmethod
57
+ def from_json(cls, json_str: str) -> 'HaiMessage':
58
+ """Create message from JSON string."""
59
+ data = json.loads(json_str)
60
+ return cls(
61
+ id=data.get("id", str(uuid.uuid4())),
62
+ topic=data["topic"],
63
+ payload=data["payload"],
64
+ timestamp=data.get("timestamp", datetime.utcnow().isoformat())
65
+ )
@@ -0,0 +1,24 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Topic(str, Enum):
5
+ """
6
+ Represents a collection of predefined topics as an enumeration.
7
+
8
+ This class is an enumeration that defines constant string values for use
9
+ as topic identifiers. These topics represent specific actions or messages
10
+ within a messaging or vector database management context. It ensures
11
+ consistent usage of these predefined topics across the application.
12
+
13
+ syntax: [hai].[source].[destination].[action]
14
+
15
+ """
16
+ # AI to Telegram
17
+ AI_SEND_TG_CHAT_MESSAGE = "hai.ai.tg.chat.send"
18
+
19
+ # AI to vector database
20
+ AI_VECTORS_SAVE = "hai.ai.vectors.save"
21
+ AI_VECTORS_QUERY = "hai.ai.vectors.query"
22
+
23
+ # TG to AI
24
+ TG_SEND_AI_CHAT_MESSAGE = "hai.tg.ai.chat.send"
File without changes
@@ -0,0 +1,86 @@
1
+ from typing import Optional, Callable, Any
2
+
3
+ import nats
4
+ from nats.aio.client import Client as NatsClient
5
+
6
+ from src.h_message_bus.infrastructure.nats_config import NatsConfig
7
+
8
+
9
+ class NatsClientRepository:
10
+ """
11
+ Repository for managing connection and interaction with a NATS server.
12
+
13
+ This class provides methods to establish a connection with a NATS server,
14
+ publish and subscribe to subjects, send requests and handle responses, and
15
+ cleanly disconnect from the server. It abstracts the connection and ensures
16
+ seamless communication with the NATS server.
17
+
18
+ :ivar config: Configuration details for the NATS client, including server
19
+ connection parameters, timeouts, and limits.
20
+ :type config: NatsConfig
21
+ :ivar client: Instance of the NATS client used for communication. Initialized
22
+ as None and assigned upon connecting to a NATS server.
23
+ :type client: Optional[NatsClient]
24
+ :ivar subscriptions: List of active subscriptions for NATS subjects.
25
+ :type subscriptions: list
26
+ """
27
+
28
+ def __init__(self, config: NatsConfig):
29
+ self.config = config
30
+ self.client: NatsClient | None = None
31
+
32
+ self.subscriptions = []
33
+
34
+ async def connect(self) -> None:
35
+ """Connect to NATS server."""
36
+ if self.client and self.client.is_connected:
37
+ return
38
+
39
+ self.client = await nats.connect(
40
+ servers=self.config.server,
41
+ max_reconnect_attempts=self.config.max_reconnect_attempts,
42
+ reconnect_time_wait=self.config.reconnect_time_wait,
43
+ connect_timeout=self.config.connection_timeout,
44
+ ping_interval=self.config.ping_interval,
45
+ max_outstanding_pings=self.config.max_outstanding_pings
46
+ )
47
+
48
+ async def publish(self, subject: str, payload: bytes) -> None:
49
+ """Publish raw message to NATS."""
50
+ if not self.client or not self.client.is_connected:
51
+ await self.connect()
52
+
53
+ await self.client.publish(subject, payload)
54
+
55
+ async def subscribe(self, subject: str, callback: Callable) -> Any:
56
+ """Subscribe to a subject with a callback."""
57
+ if not self.client or not self.client.is_connected:
58
+ await self.connect()
59
+
60
+ subscription = await self.client.subscribe(subject, cb=callback)
61
+ self.subscriptions.append(subscription)
62
+ return subscription
63
+
64
+ async def request(self, subject: str, payload: bytes, timeout: float = 2.0) -> Optional[bytes]:
65
+ """Send a request and get raw response."""
66
+ if not self.client or not self.client.is_connected:
67
+ await self.connect()
68
+
69
+ try:
70
+ response = await self.client.request(subject, payload, timeout=timeout)
71
+ return response.data
72
+ except Exception as e:
73
+ print(f"NATS request failed: {e}")
74
+ return None
75
+
76
+ async def close(self) -> None:
77
+ """Close all subscriptions and NATS connection."""
78
+ if self.client and self.client.is_connected:
79
+ # Unsubscribe from all subscriptions
80
+ for sub in self.subscriptions:
81
+ await sub.unsubscribe()
82
+
83
+ # Drain and close connection
84
+ await self.client.drain()
85
+ self.client = None
86
+ self.subscriptions = []
@@ -0,0 +1,31 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class NatsConfig:
6
+ """
7
+ Configuration class for NATS client.
8
+
9
+ This class encapsulates the configuration options required for connecting and
10
+ interacting with a NATS (NATS.io) server. It includes options for setting
11
+ server details, reconnection behavior, timeouts, and ping settings.
12
+
13
+ :ivar server: The address of the NATS server to connect to.
14
+ :type server: str
15
+ :ivar max_reconnect_attempts: The maximum number of reconnection attempts allowed.
16
+ :type max_reconnect_attempts: int
17
+ :ivar reconnect_time_wait: The time duration to wait between reconnection attempts, in seconds.
18
+ :type reconnect_time_wait: int
19
+ :ivar connection_timeout: The timeout duration for establishing a connection, in seconds.
20
+ :type connection_timeout: int
21
+ :ivar ping_interval: The interval for sending ping frames to the server, in seconds.
22
+ :type ping_interval: int
23
+ :ivar max_outstanding_pings: The maximum number of ping requests allowed without receiving a response.
24
+ :type max_outstanding_pings: int
25
+ """
26
+ server: str
27
+ max_reconnect_attempts: int = 10
28
+ reconnect_time_wait: int = 2
29
+ connection_timeout: int = 2
30
+ ping_interval: int = 20
31
+ max_outstanding_pings: int = 5
@@ -0,0 +1,277 @@
1
+ Metadata-Version: 2.4
2
+ Name: h_message_bus
3
+ Version: 0.0.3
4
+ Summary: Message bus integration for HAI
5
+ Author-email: shoebill <shoebill.hai@gmail.com>
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: python-dotenv~=1.1.0
12
+ Requires-Dist: nats-py~=2.10.0
13
+ Provides-Extra: dev
14
+ Requires-Dist: pytest; extra == "dev"
15
+
16
+ # H Message Bus
17
+
18
+ A message bus integration for HAI applications based on NATS.io
19
+
20
+ ## Overview
21
+
22
+ H Message Bus provides a robust, asynchronous messaging infrastructure built on NATS.io for HAI applications. It enables seamless communication between components through a publish-subscribe pattern, supporting both fire-and-forget messaging and request-response patterns.
23
+
24
+ ## Features
25
+
26
+ - **Asynchronous Communication**: Built for modern, non-blocking I/O operations
27
+ - **Flexible Message Routing**: Publish and subscribe to specific topics
28
+ - **High Reliability**: Automatic reconnection handling and configurable timeouts
29
+ - **Simple API**: Focus on core messaging functionality with minimal dependencies
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ pip install h_message_bus
35
+ ```
36
+
37
+ ## Requirements
38
+
39
+ - Python 3.10+
40
+ - NATS.io server (can be run via Docker)
41
+
42
+ ## Topics
43
+
44
+ H Message Bus includes predefined topics following the convention: `hai.[source].[destination].[action]`
45
+
46
+ Available topics:
47
+
48
+ | Topic Constant | Topic String | Description |
49
+ |---------------------------------|------------------------|-------------------------------------|
50
+ | `Topic.AI_SEND_TG_CHAT_MESSAGE` | `hai.ai.tg.chat.send` | AI sending message to Telegram chat |
51
+ | `Topic.AI_VECTORS_SAVE` | `hai.ai.vectors.save` | AI saving data to vector database |
52
+ | `Topic.AI_VECTORS_QUERY` | `hai.ai.vectors.query` | AI querying vector database |
53
+ | `Topic.TG_SEND_AI_CHAT_MESSAGE` | `hai.tg.ai.chat.send` | Telegram sending message to AI |
54
+
55
+ You can use these predefined topics or create your own topic strings.
56
+
57
+ ## Quick Start
58
+
59
+ ### Start a NATS Server
60
+
61
+ The easiest way to get started is with Docker:
62
+
63
+ ```bash
64
+ docker-compose up -d
65
+ ```
66
+
67
+ ### Create a Publisher
68
+
69
+ ```python
70
+ import asyncio
71
+ import uuid
72
+ from h_message_bus import NatsConfig, NatsPublisherAdapter, HaiMessage, Topic
73
+
74
+ async def main():
75
+ # Configure NATS connection
76
+ config = NatsConfig(server="nats://localhost:4222")
77
+
78
+ # Create publisher adapter
79
+ publisher = NatsPublisherAdapter(config)
80
+
81
+ # Connect to NATS
82
+ await publisher.connect()
83
+
84
+ # Create and publish a message using a predefined topic
85
+ message = HaiMessage(
86
+ message_id=str(uuid.uuid4()),
87
+ sender="service-a",
88
+ topic=Topic.TG_SEND_AI_CHAT_MESSAGE,
89
+ payload={"text": "Hello AI, this is a message from Telegram", "chat_id": 12345}
90
+ )
91
+
92
+ # Publish message
93
+ await publisher.publish(message)
94
+
95
+ # Clean up
96
+ await publisher.close()
97
+
98
+ if __name__ == "__main__":
99
+ asyncio.run(main())
100
+ ```
101
+
102
+ ### Create a Subscriber
103
+
104
+ ```python
105
+ import asyncio
106
+ from h_message_bus import NatsConfig, NatsSubscriberAdapter, HaiMessage, Topic
107
+
108
+ async def message_handler(message: HaiMessage):
109
+ print(f"Received message: {message.message_id}")
110
+ print(f"From: {message.sender}")
111
+ print(f"Topic: {message.topic}")
112
+ print(f"Payload: {message.payload}")
113
+
114
+ async def main():
115
+ # Configure NATS connection
116
+ config = NatsConfig(server="nats://localhost:4222")
117
+
118
+ # Create subscriber
119
+ subscriber = NatsSubscriberAdapter(config)
120
+
121
+ # Connect to NATS
122
+ await subscriber.connect()
123
+
124
+ # Subscribe to a topic
125
+ await subscriber.subscribe(Topic.TG_SEND_AI_CHAT_MESSAGE, message_handler)
126
+
127
+ # Keep the application running
128
+ try:
129
+ print("Subscriber running. Press Ctrl+C to exit.")
130
+ while True:
131
+ await asyncio.sleep(1)
132
+ except KeyboardInterrupt:
133
+ # Clean up
134
+ await subscriber.close()
135
+
136
+ if __name__ == "__main__":
137
+ asyncio.run(main())
138
+ ```
139
+
140
+ ## Advanced Usage
141
+
142
+ ### Request-Response Pattern
143
+
144
+ ```python
145
+ import asyncio
146
+ import uuid
147
+ from h_message_bus import NatsConfig, NatsPublisherAdapter, HaiMessage, Topic
148
+
149
+ async def main():
150
+ config = NatsConfig(server="nats://localhost:4222")
151
+ publisher = NatsPublisherAdapter(config)
152
+
153
+ # Connect to NATS
154
+ await publisher.connect()
155
+
156
+ request_message = HaiMessage(
157
+ message_id=str(uuid.uuid4()),
158
+ sender="client-service",
159
+ topic=Topic.AI_VECTORS_QUERY,
160
+ payload={"query": "find similar documents", "limit": 10}
161
+ )
162
+
163
+ # Send request and wait for response (with timeout)
164
+ response = await publisher.request(request_message, timeout=5.0)
165
+
166
+ if response:
167
+ print(f"Received response: {response.payload}")
168
+ else:
169
+ print("Request timed out")
170
+
171
+ await publisher.close()
172
+
173
+ if __name__ == "__main__":
174
+ asyncio.run(main())
175
+ ```
176
+
177
+ ### Creating a Service with Request Handler
178
+
179
+ ```python
180
+ import asyncio
181
+ import uuid
182
+ from h_message_bus import NatsConfig, NatsSubscriberAdapter, NatsPublisherAdapter, HaiMessage, Topic
183
+
184
+ async def request_handler(request: HaiMessage):
185
+ print(f"Received request: {request.message_id}")
186
+ print(f"Payload: {request.payload}")
187
+
188
+ # Process the request
189
+ result = {"status": "success", "data": {"result": 42}}
190
+
191
+ # Create a response message
192
+ return HaiMessage(
193
+ message_id=str(uuid.uuid4()),
194
+ sender="service-b",
195
+ topic=f"{request.topic}.response",
196
+ payload=result,
197
+ correlation_id=request.message_id
198
+ )
199
+
200
+ async def main():
201
+ # Configure NATS connection
202
+ config = NatsConfig(server="nats://localhost:4222")
203
+
204
+ # Create subscriber for handling requests
205
+ subscriber = NatsSubscriberAdapter(config)
206
+ publisher = NatsPublisherAdapter(config)
207
+
208
+ # Connect to NATS
209
+ await subscriber.connect()
210
+ await publisher.connect()
211
+
212
+ # Register request handler for vector database queries
213
+ await subscriber.subscribe_with_response(Topic.AI_VECTORS_QUERY, request_handler, publisher)
214
+
215
+ # Keep the application running
216
+ try:
217
+ print("Service running. Press Ctrl+C to exit.")
218
+ while True:
219
+ await asyncio.sleep(1)
220
+ except KeyboardInterrupt:
221
+ # Clean up
222
+ await subscriber.close()
223
+ await publisher.close()
224
+
225
+ if __name__ == "__main__":
226
+ asyncio.run(main())
227
+ ```
228
+
229
+ ## Configuration Options
230
+
231
+ The `NatsConfig` class allows you to customize your NATS connection:
232
+
233
+ | Parameter | Description | Default |
234
+ |--------------------------|----------------------------------------------|---------------|
235
+ | `server` | NATS server address | Required |
236
+ | `max_reconnect_attempts` | Maximum reconnection attempts | 10 |
237
+ | `reconnect_time_wait` | Time between reconnection attempts (seconds) | 2 |
238
+ | `connection_timeout` | Connection timeout (seconds) | 2 |
239
+ | `ping_interval` | Interval for ping frames (seconds) | 20 |
240
+ | `max_outstanding_pings` | Maximum unanswered pings before disconnect | 5 |
241
+ | `max_payload` | Maximum size of the payload in bytes | 1048576 (1MB) |
242
+
243
+ ## API Reference
244
+
245
+ ### Exported Classes
246
+
247
+ The following classes are exported directly from the package:
248
+
249
+ - `NatsConfig` - Configuration for the NATS connection
250
+ - `HaiMessage` - Message structure for HAI communication
251
+ - `NatsPublisherAdapter` - Adapter for publishing messages
252
+ - `NatsSubscriberAdapter` - Adapter for subscribing to messages
253
+ - `MessageProcessor` - Processing incoming messages
254
+ - `NatsClientRepository` - Low-level NATS client operations
255
+ - `Topic` - Enumeration of predefined topic strings
256
+
257
+ ### HaiMessage Structure
258
+
259
+ The `HaiMessage` class is the core data structure used for all messaging:
260
+
261
+ ```python
262
+ class HaiMessage:
263
+ message_id: str # Unique identifier for the message
264
+ sender: str # Identifier of the sender
265
+ topic: str # The topic or channel for the message
266
+ payload: dict # Actual message data
267
+ correlation_id: str = None # Optional reference to a related message
268
+ timestamp: float = None # Optional message creation timestamp
269
+ ```
270
+
271
+ ## Contributing
272
+
273
+ Contributions are welcome! Please feel free to submit a Pull Request.
274
+
275
+ ## License
276
+
277
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,19 @@
1
+ h_message_bus/__init__.py,sha256=kWqtL6JKd1mUqsFqwzdQuV1vhKjvv1bxh4ShMHEhrHM,507
2
+ h_message_bus/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ h_message_bus/adapters/nats_message_adapter.py,sha256=Xx16NPk1b7nNuy5BWw9F9SUBqjO98TQdxl3kfQzV0_E,1403
4
+ h_message_bus/adapters/nats_publisher_adapter.py,sha256=GaLqa0xJrq-2Ch5BDk3KCcTMv1RIzLzP13lEEoOImY4,1811
5
+ h_message_bus/adapters/nats_subscriber_adapter.py,sha256=vY6Cj90CLJmbWGXwH9VE6cPL0TUYdkywNkCjC12EV4Q,2136
6
+ h_message_bus/application/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ h_message_bus/application/message_processor.py,sha256=mGW3TVpMtEV0eSs3-t6G9ny12kbwdwRlm1IfURv856A,743
8
+ h_message_bus/application/message_publisher.py,sha256=6XimOGi2HpxTA1_y1akwCXqZ6HF6KkxUvwjy1XoAVPw,851
9
+ h_message_bus/application/message_subcriber.py,sha256=2yqUUHVHtZlA6-zzyHzghdWQ7ZmdcFic5c0xi_rgG-M,741
10
+ h_message_bus/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ h_message_bus/domain/hai_message.py,sha256=mODVLRx_hgrnK9dbw57MiFATAiRwsgQ2TAOTA7r5Fcc,2108
12
+ h_message_bus/domain/topics.py,sha256=a3VfQuItmHMaHaDWf2N9DgU8ASUh3-EHHB12YIJPvNw,769
13
+ h_message_bus/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ h_message_bus/infrastructure/nats_client_repository.py,sha256=blGsJzqGzdqp0MyGxb_HoZgtqVJ4TfZAFFpsucOYWSU,3359
15
+ h_message_bus/infrastructure/nats_config.py,sha256=Yzqqd1bCfmUv_4FOnA1dvqIpakzV0BUL2_nXQcndWvo,1304
16
+ h_message_bus-0.0.3.dist-info/METADATA,sha256=AdWg-lw8muM9nRoDE8RACUkGdCgw6PMFA4889S5-wrg,8870
17
+ h_message_bus-0.0.3.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
18
+ h_message_bus-0.0.3.dist-info/top_level.txt,sha256=7feCw9I0yIIqsYsVzUMYvCCmUTOiGX1a5F2VbSkFscc,14
19
+ h_message_bus-0.0.3.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (78.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ h_message_bus