Metadata-Version: 2.5
Name: py-stinger-nng
Version: 0.1.1
Summary: Stinger-style IPC (signals, properties, methods) over NNG
Author-email: Jacob Brunson <github@jacobbrunson.com>
License-Expression: MIT
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: py-stinger-conn-iface==0.1.2
Requires-Dist: pyfory>=1.7.2
Requires-Dist: pynng>=0.9.0
Description-Content-Type: text/markdown

# py-stinger-nng

Stinger-style IPC (signals, properties, methods) over NNG — a Python pub/sub broker implementing the IBrokerConnection interface with topic filtering, retained state, and cross-platform networking.

## Features

- **Topic-filtered subscriptions**: Subscribe to specific topics or topic prefixes
- **Retained state**: Messages marked with `retain=True` are stored by the server and delivered to clients that join later
- **Client-to-client relaying**: The server can relay messages between clients
- **Background connection management**: Both client sockets dial in the background; reconnection is automatic after server restarts
- **Thread-safe**: Safe to call from multiple threads and from within message callbacks

## Installation

```bash
pip install py-stinger-nng
```

## Quick Start

```python
from py_stinger_nng import StingerNngServer, StingerNngClient
from pystingerconniface import Message

# Start a server on ports 15555 (publish) and 15556 (receive)
with StingerNngServer(15555, 15556) as server:
    # Create a client
    with StingerNngClient(15555, 15556) as client:
        # Subscribe to a topic
        def on_message(msg: Message) -> None:
            print(f"Received: {msg.topic} = {msg.payload}")
        
        client.subscribe("sensor/", on_message)
        
        # Publish a message
        msg = Message(topic="sensor/temperature", payload=b"21.5")
        client.publish(msg).result()
```

## Architecture

- **StingerNngServer**: Runs on two ports — PUB socket for publishing, PULL socket for receiving. Dispatches messages to all matching subscriptions, manages retained state, and relays client messages.
- **StingerNngClient**: Connects to the server with SUB and PUSH sockets. Handles topic filtering at the socket level and syncs retained state on connect.

## Key Methods

Both `StingerNngServer` and `StingerNngClient` implement `IBrokerConnection`:

- `publish(message)` → Future[None]: Send a message
- `subscribe(topic, callback=None, qos=1)` → int: Subscribe to a topic, returns a subscription ID
- `unsubscribe(sub_id)` → bool: Cancel a subscription
- `add_message_callback(callback)`: Register a callback for all unsubscribed messages
- `close()`: Shut down the connection
- `is_connected()` → bool: Check connection status
- `client_id` → str: The unique identifier for this connection
- `online_topic` → str | None: The topic for liveness announcements (if configured)

See [examples/pubsub.py](examples/pubsub.py) for a complete working example.
