puda-comms 0.0.2__py3-none-any.whl → 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.
@@ -10,7 +10,6 @@ This service handles:
10
10
  import asyncio
11
11
  import json
12
12
  import logging
13
- import os
14
13
  import signal
15
14
  from datetime import datetime, timezone
16
15
  from typing import Dict, Any, Optional, Tuple
@@ -178,8 +177,16 @@ class ResponseHandler:
178
177
  if key in self._pending_responses:
179
178
  del self._pending_responses[key]
180
179
 
180
+ def cancel_all_pending(self):
181
+ """Cancel all pending responses by setting their events. This wakes up any waiting tasks immediately."""
182
+ for pending in self._pending_responses.values():
183
+ pending['event'].set()
184
+
181
185
  async def cleanup(self):
182
186
  """Clean up subscriptions."""
187
+ # Cancel all pending responses first to wake up waiting tasks
188
+ self.cancel_all_pending()
189
+
183
190
  if self._queue_consumer:
184
191
  try:
185
192
  await self._queue_consumer.unsubscribe()
@@ -200,11 +207,6 @@ class CommandService:
200
207
  Handles connection management, command parsing, and response handling.
201
208
  Can send commands to multiple machines.
202
209
 
203
- Supports async context manager usage for automatic cleanup:
204
- async with CommandService() as service:
205
- await service.send_queue_command(...)
206
- # Automatically disconnects on exit
207
-
208
210
  Automatically registers signal handlers (SIGTERM, SIGINT) for graceful shutdown.
209
211
  """
210
212
 
@@ -212,20 +214,19 @@ class CommandService:
212
214
 
213
215
  def __init__(
214
216
  self,
215
- servers: Optional[list[str]] = None
217
+ servers: list[str]
216
218
  ):
217
219
  """
218
220
  Initialize NATS service.
219
221
 
220
222
  Args:
221
- servers: List of NATS server URLs. If None, reads from NATS_SERVERS env var.
223
+ servers: List of NATS server URLs. Must be a non-empty list.
224
+
225
+ Raises:
226
+ ValueError: If servers is None or empty.
222
227
  """
223
- if servers is None:
224
- nats_servers_env = os.getenv(
225
- "NATS_SERVERS",
226
- "nats://192.168.50.201:4222,nats://192.168.50.201:4223,nats://192.168.50.201:4224"
227
- )
228
- servers = [s.strip() for s in nats_servers_env.split(",")]
228
+ if servers is None or len(servers) == 0:
229
+ raise ValueError("Please provide a non-empty list of NATS server URLs")
229
230
 
230
231
  self.servers = servers
231
232
  self.nc: Optional[nats.NATS] = None
@@ -254,24 +255,50 @@ class CommandService:
254
255
  """
255
256
  Connect to NATS servers.
256
257
 
258
+ Limits connection attempts to 3. After 3 failed attempts, gives up and logs error.
259
+
257
260
  Returns:
258
261
  True if connected successfully, False otherwise
259
262
  """
260
263
  if self._connected:
261
264
  return True
262
265
 
263
- try:
264
- self.nc = await nats.connect(servers=self.servers)
265
- self.js = self.nc.jetstream()
266
-
267
- self._connected = True
268
- logger.info("Connected to NATS servers: %s", self.servers)
269
- return True
270
-
271
- except Exception as e:
272
- logger.error("Failed to connect to NATS: %s", e)
273
- self._connected = False
274
- return False
266
+ max_attempts = 3
267
+ connect_timeout = 3 # 3 seconds timeout per connection attempt
268
+
269
+ for attempt in range(1, max_attempts + 1):
270
+ try:
271
+ logger.info("Connection attempt %d/%d to NATS servers: %s", attempt, max_attempts, self.servers)
272
+ self.nc = await asyncio.wait_for(
273
+ nats.connect(
274
+ servers=self.servers,
275
+ connect_timeout=connect_timeout,
276
+ reconnect_time_wait=2,
277
+ max_reconnect_attempts=0 # No reconnection during initial connection
278
+ ),
279
+ timeout=connect_timeout + 1 # Slightly longer timeout for the wait_for
280
+ )
281
+ self.js = self.nc.jetstream()
282
+
283
+ self._connected = True
284
+ logger.info("Connected to NATS servers")
285
+ return True
286
+
287
+ except asyncio.TimeoutError:
288
+ logger.warning("Connection attempt %d/%d timed out after %d seconds", attempt, max_attempts, connect_timeout)
289
+ if attempt < max_attempts:
290
+ logger.info("Retrying connection...")
291
+ else:
292
+ logger.error("Failed to connect after %d attempts. Giving up.", max_attempts)
293
+ except Exception as e:
294
+ logger.warning("Connection attempt %d/%d failed: %s", attempt, max_attempts, e)
295
+ if attempt < max_attempts:
296
+ logger.info("Retrying connection...")
297
+ else:
298
+ logger.error("Failed to connect after %d attempts. Giving up.", max_attempts)
299
+
300
+ self._connected = False
301
+ return False
275
302
 
276
303
  async def _get_response_handler(self, machine_id: str) -> ResponseHandler:
277
304
  """
@@ -261,6 +261,7 @@ class MachineClient:
261
261
  try:
262
262
  self.nc = await nats.connect(
263
263
  servers=self.servers,
264
+ connect_timeout=10, # 10 seconds timeout for initial connection
264
265
  reconnect_time_wait=2,
265
266
  max_reconnect_attempts=-1,
266
267
  error_cb=self._error_callback,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: puda-comms
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: Communication library for the PUDA platform.
5
5
  Author: zhao
6
6
  Author-email: zhao <20024592+agentzhao@users.noreply.github.com>
@@ -292,14 +292,30 @@ else:
292
292
 
293
293
  ### Configuration
294
294
 
295
- The `CommandService` reads NATS server URLs from the `NATS_SERVERS` environment variable, or defaults to:
295
+ #### NATS Server Configuration
296
+
297
+ The `CommandService` requires NATS server URLs to be specified explicitly. There are no default values. You must provide servers in one of two ways:
298
+
299
+ **Option 1: Via environment variable (comma-separated string)**
300
+
301
+ Set the `NATS_SERVERS` environment variable with comma-separated server URLs:
302
+
303
+ ```bash
304
+ export NATS_SERVERS="nats://192.168.50.201:4222,nats://192.168.50.201:4223,nats://192.168.50.201:4224"
296
305
  ```
297
- nats://192.168.50.201:4222,nats://192.168.50.201:4223,nats://192.168.50.201:4224
306
+
307
+ Then parse it when creating a `CommandService`:
308
+ ```python
309
+ import os
310
+ nats_servers = [s.strip() for s in os.getenv("NATS_SERVERS", "").split(",") if s.strip()]
311
+ service = CommandService(servers=nats_servers)
298
312
  ```
299
313
 
300
- You can also specify servers explicitly:
314
+ **Option 2: Directly as a list**
315
+
316
+ Specify servers directly when creating a `CommandService`:
301
317
  ```python
302
- service = CommandService(servers=["nats://localhost:4222"])
318
+ service = CommandService(servers=["nats://192.168.50.201:4222", "nats://192.168.50.201:4223", "nats://192.168.50.201:4224"])
303
319
  ```
304
320
  ## Validation
305
321
 
@@ -0,0 +1,8 @@
1
+ puda_comms/__init__.py,sha256=lntvVFJJez_rv5lZy5mYj4_43B9Y3NRNzxWfBuSAQ1M,194
2
+ puda_comms/command_service.py,sha256=E5kGzl2hjkSTubxv01nxuo9XMXHY5aTEsn-k3IDJVB8,24727
3
+ puda_comms/execution_state.py,sha256=aTaejCnJgg1y_FP-ymIC1GQzqC81FIWo0RZ18XzAQnA,2881
4
+ puda_comms/machine_client.py,sha256=r8oSnkRoqhKykvyR94kGlA1vRrCKLq-o9uNZQftxqDU,33120
5
+ puda_comms/models.py,sha256=cVH5uKzyLmjzPeBcm3RIJMTkoynmxqe_P26GtZwlIN8,3500
6
+ puda_comms-0.0.3.dist-info/WHEEL,sha256=ZyFSCYkV2BrxH6-HRVRg3R9Fo7MALzer9KiPYqNxSbo,79
7
+ puda_comms-0.0.3.dist-info/METADATA,sha256=Fnf_YWeOZAcefPUTY976BUT95M0w-8bSqAhjVMkmjxA,11158
8
+ puda_comms-0.0.3.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- puda_comms/__init__.py,sha256=lntvVFJJez_rv5lZy5mYj4_43B9Y3NRNzxWfBuSAQ1M,194
2
- puda_comms/command_service.py,sha256=B4fKiQNF0slvGS1fXVoh5UZax_-xk4IS-KT96teSRfg,23272
3
- puda_comms/execution_state.py,sha256=aTaejCnJgg1y_FP-ymIC1GQzqC81FIWo0RZ18XzAQnA,2881
4
- puda_comms/machine_client.py,sha256=F2i0BYBuOLjKAnfZAblNrb3Lzs0yhEO1d4XA-k_dkIU,33039
5
- puda_comms/models.py,sha256=cVH5uKzyLmjzPeBcm3RIJMTkoynmxqe_P26GtZwlIN8,3500
6
- puda_comms-0.0.2.dist-info/WHEEL,sha256=ZyFSCYkV2BrxH6-HRVRg3R9Fo7MALzer9KiPYqNxSbo,79
7
- puda_comms-0.0.2.dist-info/METADATA,sha256=jHHcSSmdWOykobTsieX2bqDeRtqSaqdUd-xZeeWxJZ8,10585
8
- puda_comms-0.0.2.dist-info/RECORD,,