Skip to content
Draft
Show file tree
Hide file tree
Changes from 90 commits
Commits
Show all changes
127 commits
Select commit Hold shift + click to select a range
2650f9e
Add nats-client package
caspervonb Sep 22, 2025
850486d
Use named tuples for parsing
caspervonb Oct 3, 2025
dd075df
Add `__version__`
caspervonb Oct 4, 2025
78912e1
Make operation parsing case-insensitive in message protocol
caspervonb Oct 4, 2025
484a5e2
Raise ParseError for header lines missing colon
caspervonb Oct 4, 2025
d93f72e
Improve error reporting for unknown operation using repr
caspervonb Oct 4, 2025
4de3c85
Refactor protocol message parsing into more readable dispatch
caspervonb Oct 4, 2025
7e85715
Handle IPv6 addresses correctly in server URLs
caspervonb Oct 4, 2025
56b38de
Add no_randomize option to connect and test sequential cluster reconnect
caspervonb Oct 4, 2025
91183fd
Refactor Connection to use Protocol instead of ABC
caspervonb Oct 4, 2025
e1f5a53
Add explicit attribute declarations to client classes
caspervonb Oct 4, 2025
22b3530
Remove redundant comments and add Reader protocol to parser module
caspervonb Oct 4, 2025
39358ca
Switch build system from Hatchling to Setuptools
caspervonb Oct 4, 2025
2693ab8
Add nats-client to workspace members in pyproject.toml
caspervonb Oct 4, 2025
fff225b
Add dev dependencies for nats-client and update uv.lock
caspervonb Oct 4, 2025
82f9351
Add asdict method to Headers and use in Client
caspervonb Oct 4, 2025
451219b
Improve cluster reconnect test to shut down connected server
caspervonb Oct 4, 2025
e1c4666
Parametrize cluster reconnect test by cluster size
caspervonb Oct 4, 2025
a6327a9
Prevent concurrent reconnection attempts with asyncio.Lock
caspervonb Oct 4, 2025
138ca95
Require Python 3.11+ and remove dependency on typing extensions
caspervonb Oct 4, 2025
f17f594
Refactor message parsing functions and update tests
caspervonb Oct 5, 2025
7c1c919
Refactor reconnection logic for clarity and remove redundant checks
caspervonb Oct 7, 2025
49e99ef
Handle exceptions when closing connection in Client
caspervonb Oct 7, 2025
c6181ce
Close connection only if it is currently connected
caspervonb Oct 7, 2025
044ee5b
Refactor reconnect attempts variable naming for clarity
caspervonb Oct 7, 2025
7e07832
Refactor server pool management and remove _collect_servers
caspervonb Oct 7, 2025
5e7aebd
Log and handle CancelledError and TimeoutError on connect
caspervonb Oct 7, 2025
9686354
Fix exception handling to use asyncio.TimeoutError
caspervonb Oct 7, 2025
59ebbc8
Avoid duplicate servers when updating server pool
caspervonb Oct 7, 2025
23f854b
Set reconnect_time_wait to 0.0 in cluster reconnect test
caspervonb Oct 7, 2025
a6d91ee
Reduce client connection timeout in cluster reconnect test
caspervonb Oct 7, 2025
5f06a09
Add reconnect_timeout parameter to connect function
caspervonb Oct 7, 2025
13969e5
Rename reconnect_attempts to reconnect_max_attempts
caspervonb Oct 7, 2025
a7a1bdf
Fix cluster reconnect test to match server by port only
caspervonb Oct 7, 2025
171ad83
Remove 2-node cluster test from cluster reconnect parametrize
caspervonb Oct 7, 2025
345382f
Format with ruff
caspervonb Oct 8, 2025
51553bb
Fix lints
caspervonb Oct 8, 2025
dce2956
Fix more lints
caspervonb Oct 8, 2025
6c78343
Format again
caspervonb Oct 8, 2025
6d19ac8
Add nats-jetstream package
caspervonb Sep 23, 2025
324aa15
Remove is_active property from MessageHandler
caspervonb Oct 7, 2025
43ccf65
Add type annotations for MessageHandler attributes
caspervonb Oct 7, 2025
2e8f08e
Add type annotations for PullMessageBatch attributes
caspervonb Oct 7, 2025
b09af62
Add type annotations to PullMessageStream attributes
caspervonb Oct 7, 2025
0df512c
Add type annotations for PullConsumer attributes
caspervonb Oct 7, 2025
d811201
Rename batch parameter to max_messages in consume method
caspervonb Oct 7, 2025
d908a7b
Add keyword-only separator to consume method signatures
caspervonb Oct 7, 2025
a2f69e5
Remove redundant expires parameter from `consume`
caspervonb Oct 7, 2025
1a679ac
Move __all__ definition to end of message.py
caspervonb Oct 7, 2025
524404a
Migrate pyproject.toml to uv
caspervonb Oct 7, 2025
2124bc5
Fix failing tests
caspervonb Oct 7, 2025
361dd95
Fix __all__ order
caspervonb Oct 7, 2025
fedd5e1
Fix implicit concatenation
caspervonb Oct 7, 2025
c6918c9
Include missing action in consumer request payload
caspervonb Oct 7, 2025
9834d83
Remove heartbeat fetch test due to removed functionality
caspervonb Oct 7, 2025
b820fa6
Use Error instead of ValueError in consumer update test
caspervonb Oct 8, 2025
2d5a8e6
Update test for duplicate consumer name with different config
caspervonb Oct 8, 2025
1883983
Refactor APIStats.from_response
caspervonb Oct 8, 2025
8cccf70
Refactor AccountLimits.from_response
caspervonb Oct 8, 2025
5ec9c05
Refactor Tier.from_response
caspervonb Oct 8, 2025
f3681b3
Refactor AccountInfo.from_response
caspervonb Oct 8, 2025
a8dcfa2
Refactor to use fully qualified api.Client name.
caspervonb Oct 8, 2025
fe02bdb
Remove stale comment
caspervonb Oct 8, 2025
61b0c5c
Expand StreamConfig.from_response for explicit field mapping
caspervonb Oct 8, 2025
128e7c0
Refactor StreamInfo.from_response for clarity and readability
caspervonb Oct 8, 2025
bc6ef83
Refactor ConsumerInfo.from_response
caspervonb Oct 8, 2025
b181e59
Support more reply subject formats in `message.Metadata` parsing
caspervonb Oct 8, 2025
5c16e44
Raise ValueError for invalid JetStream reply subject formats
caspervonb Oct 8, 2025
5aa929c
Add ClusterInfo and PeerInfo dataclasses to model cluster state
caspervonb Oct 8, 2025
2568450
Refactor StreamState.from_response for clarity and readability
caspervonb Oct 8, 2025
0c59b93
Add StreamSource, ExternalStreamSource, and SubjectTransform classes
caspervonb Oct 8, 2025
0d5cb07
Add StreamSourceInfo class and update StreamInfo to use it
caspervonb Oct 8, 2025
dd5f029
Add Placement dataclass and integrate with StreamConfig
caspervonb Oct 8, 2025
7c818a9
Add Republish dataclass and integrate with StreamConfig
caspervonb Oct 8, 2025
93abd31
Add StreamConsumerLimits dataclass and integrate with StreamConfig
caspervonb Oct 8, 2025
e7e104a
Refactor response type handling and add check_response tests
caspervonb Oct 8, 2025
892bd3e
Make upsert_consumer a private method
caspervonb Oct 8, 2025
7a2cd99
Add StreamConfig dict-to-dataclass and to_request conversion
caspervonb Oct 8, 2025
5d5ef16
Use None for unlimited StreamConfig limits instead of sentinel values
caspervonb Oct 8, 2025
d68c61c
Add type aliases for stream config enums and update usage
caspervonb Oct 8, 2025
28b11dd
Add docstrings to dataclasses and fields
caspervonb Oct 8, 2025
aa40a94
Add strict field validation to from_response methods
caspervonb Oct 8, 2025
63c3c9e
Remove Python 3.11 from test matrix
caspervonb Oct 8, 2025
a744bd8
Overhaul type generation
caspervonb Oct 8, 2025
1b10d24
Introduce ConsumerConfig dataclass and refactor consumer creation
caspervonb Oct 8, 2025
dd2a364
Format with ruff instead of yapf
caspervonb Oct 8, 2025
b7b7e9f
Fix ruff lints
caspervonb Oct 8, 2025
bc54755
Fix more lints
caspervonb Oct 8, 2025
8746bfe
Remove unused imports
caspervonb Oct 8, 2025
85848e5
Add strict parameter to from_response methods
caspervonb Oct 8, 2025
a2745f5
Set from_response strict default to False
caspervonb Oct 9, 2025
0619adc
Add response validation to jetstream api
caspervonb Oct 9, 2025
cdaae90
Remove Consumer.consume
caspervonb Oct 12, 2025
751b5d1
Remove duplicate type annotation
caspervonb Oct 12, 2025
2b3514b
Implement header parsing for paths returning StreamMessage
caspervonb Oct 12, 2025
62775a9
Delete test_stream_config_none_semantics.py
caspervonb Oct 12, 2025
2dadfe9
Format
caspervonb Oct 12, 2025
17647a1
Fix lints
caspervonb Oct 12, 2025
3f7036f
Add strict mode to JetStream
caspervonb Oct 17, 2025
8502ffd
Support prioritized consumer fetching
caspervonb Oct 20, 2025
a4f7853
Add consumer pause/resume
caspervonb Oct 20, 2025
a47c7c2
Fix skipped tests
caspervonb Oct 20, 2025
3e35f47
Add tests for multiple filter_subjects
caspervonb Oct 20, 2025
eba8a6f
Refine Pull consumer status code handling
caspervonb Oct 20, 2025
13d092e
Add threshold params to pull message stream
caspervonb Oct 20, 2025
e9f2097
Add heartbeat monitoring to pull consumer and stream
caspervonb Oct 21, 2025
07e65d9
Handle 409 and pending headers in pull consumer
caspervonb Oct 21, 2025
650df40
Compute message size and use in pull consumer
caspervonb Oct 21, 2025
df891bf
Accept ConsumerConfig in update_consumer
caspervonb Oct 21, 2025
2d30ae1
Validate ConsumerConfig and use in update_consumer
caspervonb Oct 21, 2025
516bb5d
Make all api client request methods positional and use request dicts
caspervonb Oct 21, 2025
4076d94
Apply code style and formatting fixes
caspervonb Oct 21, 2025
e6b61bb
Use Stream API for consumer pause/resume in tests
caspervonb Oct 21, 2025
691a39c
Use RFC3339 strings for timestamps in API types
caspervonb Oct 21, 2025
3135f85
Convert ts fields to datetime
caspervonb Oct 21, 2025
4bbe30f
Use datetime for stream and consumer timestamps
caspervonb Oct 21, 2025
7832e77
Use timedelta for duration fields
caspervonb Oct 21, 2025
4173324
Fix timedelta tests
caspervonb Oct 21, 2025
d7c97ac
Add stream republish, transform, and metadata tests
caspervonb Oct 21, 2025
db9fec7
Run ruff format
caspervonb Oct 21, 2025
544ab00
Implement ADR-37 compliance for pull consumer
caspervonb Oct 21, 2025
acec368
Update tests to enforce ADR-37 semantics
caspervonb Oct 21, 2025
9c7dd6b
Fix unused variable in test_consumer_info_not_paused_initially
caspervonb Oct 21, 2025
384f202
Standardize UTF-8 string quoting in Message.size
caspervonb Oct 21, 2025
1950cc3
Retry publish on `NoResponders` errors
caspervonb Oct 21, 2025
ba1e69b
Add create_or_update_consumer to JetStream and Stream
caspervonb Oct 21, 2025
185c9f9
Overhaul error handling
caspervonb Oct 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
python-version: ["3.12", "3.13"]
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
nats-server-version: ["latest"]
project: ["nats-server"]
project: ["nats-server", "nats-client", "nats-jetstream"]
steps:
- name: Checkout repository
uses: actions/checkout@v5
Expand Down
82 changes: 82 additions & 0 deletions nats-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# NATS Client

A Python client for the NATS messaging system.

## Features

- Support for publish/subscribe
- Support for request/reply
- Support for queue groups
- Support for multi-value message headers

## Installation

```bash
pip install nats-client
```

## Usage

```python
import asyncio
from nats.client import connect

async def main():
client = await connect("nats://localhost:4222")

# Subscribe
async with await client.subscribe("foo") as subscription:
# Publish
await client.publish("foo", "Hello World!")

# Receive message
message = await subscription.next()
print(f"Received: {message.data}")

await client.close()

if __name__ == "__main__":
asyncio.run(main())
```

## 🚀 Performance

This client implementation delivers significant performance improvements over the nats.aio client, particularly for high-frequency, small message workloads.

Do note tho, it is not as feature complete at this point in time.

| Message Size | nats.py (python3) | nats.py (pypy3) | experimental-nats.py (python3) | experimental-nats (pypy3) | Performance Gain |
|--------------|-------------------|-----------------|--------------------------------|---------------------------|------------------|
| 1B | 127,411 | 153,009 | 1,522,673 | **5,376,113** | **35.1x** 🚀 |
| 2B | 136,485 | 148,981 | 1,544,513 | **5,396,347** | **36.2x** 🚀 |
| 4B | 131,630 | 149,297 | 1,548,191 | **5,356,600** | **35.9x** 🚀 |
| 8B | 138,229 | 141,117 | 1,530,825 | **5,307,400** | **37.6x** 🚀 |
| 16B | 140,874 | 149,826 | 1,539,244 | **5,211,168** | **34.8x** 🚀 |
| 32B | 141,427 | 146,670 | 1,515,068 | **5,115,238** | **34.9x** 🚀 |
| 64B | 145,257 | 153,542 | 1,505,724 | **5,339,967** | **34.8x** 🚀 |
| 128B | 163,181 | 164,723 | 1,479,100 | **4,923,321** | **29.9x** 🔥 |
| 256B | 145,824 | 161,017 | 1,452,996 | **4,130,165** | **25.7x** 🔥 |
| 512B | 243,641 | 277,321 | 1,297,250 | **3,430,092** | **12.4x**|
| 1K | 738,895 | 802,283 | 1,253,102 | **2,374,747** | **3.0x**|
| 2K | 696,945 | 736,925 | 1,060,123 | **1,381,177** | **1.9x**|
| 4K | 577,335 | 625,935 | 798,797 | **814,393** | **1.3x**|
| 8K | 414,077 | 463,383 | 532,429 | 450,211 | 0.97x |
| 16K | 266,104 | 309,680 | 345,651 | 228,815 | 0.74x |
| 32K | 102,460 | 128,852 | 166,028 | 125,662 | 0.98x |
| 64K | 55,208 | 63,563 | 74,359 | 56,804 | 0.89x |

### Key Performance Insights

**🎯 Sweet Spot: Small to Medium Messages**
- **35-37x faster** for tiny messages (1B-64B)
- **25-30x faster** for small messages (128B-256B)
- **12x faster** for medium messages (512B)

### Benchmark Environment

- **CPU**: Apple M3 Max
- **Memory**: 36 GB
- **Python**: 3.x
- **PyPy**: 3.x

> **Note**: Benchmarks may vary based on your specific hardware, network conditions, and NATS server configuration. We recommend running your own benchmarks for production workloads.
50 changes: 50 additions & 0 deletions nats-client/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "nats-client"
version = "0.0.0"
description = "NATS client implementation in Python"
readme = "README.md"
requires-python = ">=3.11"
license = "MIT"
keywords = ["nats", "messaging", "client"]
authors = [
{ name = "Casper Beyer", email = "[email protected]" },
]
classifiers = [
"Development Status :: 4 - Beta",
"Programming Language :: Python",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
dependencies = []

[project.urls]
Documentation = "https://github.com/nats-io/nats.py"
Issues = "https://github.com/nats-io/nats.py/issues"
Source = "https://github.com/nats-io/nats.py"

[tool.setuptools.packages.find]
where = ["src"]

[tool.uv]
dev-dependencies = [
"nats-server",
"pytest>=7.0.0",
"pytest-asyncio>=0.21.0",
"pytest-cov>=7.0.0",
"pytest-xdist>=3.0.0",
"pytest-benchmark",
]

[tool.uv.sources]
nats-server = { workspace = true }

[tool.pytest.ini_options]
asyncio_default_fixture_loop_scope = "function"
asyncio_mode = "auto"
Loading
Loading