Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
88 changes: 64 additions & 24 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,41 @@
# RobustMQ SDK — Project Guide

## What this repo is
## What is RobustMQ

Multi-language client SDK for RobustMQ, a unified messaging broker that supports MQTT, Kafka,
NATS, AMQP, and mq9 on a shared storage layer. This SDK focuses on **mq9** — the AI-native
async communication protocol built on top of NATS.
RobustMQ is a **unified messaging platform written in Rust** — one binary, one broker, zero external dependencies.
It natively runs MQTT, Kafka, NATS, AMQP, and mq9 on a **shared pluggable storage layer**.

Core architecture (3-tier, fully decoupled):
- **Broker** (stateless compute): protocol parsing, TCP/TLS/WebSocket/WSS/QUIC
- **Meta Service**: Raft-based cluster coordination, replaces ZooKeeper
- **Storage Engine**: pluggable — Memory / RocksDB / File Segment, S3 tiering

Key differentiators vs Kafka/NATS:
- Multi-protocol on one deployment (no bridging, no data silos)
- Compute-storage separation → scale independently in seconds (not hours)
- Rust: no GC pauses, predictable latency
- mq9: AI-native async mailbox protocol (see below)

## What this SDK is

Multi-language client SDK for RobustMQ. Currently implements **mq9** — more protocols (MQTT, Kafka, AMQP)
will be added as RobustMQ matures.

**Package naming strategy (Method A — single SDK per language):**
Each language ships one package that grows to cover all protocols via sub-modules.
Users install one package and import the protocol they need.

| Language | Published package | mq9 import/usage |
| ---------- | ---------------------------- | --------------------------------------------- |
| Python | `robustmq` (PyPI) | `from robustmq.mq9 import Client` |
| Go | `robustmq-sdk/go` (git tag) | `import "github.com/robustmq/robustmq-sdk/go/mq9"` |
| JavaScript | `@robustmq/sdk` (npm) | `import { MQ9Client } from '@robustmq/sdk/mq9'` |
| Java | `com.robustmq:robustmq` | `import com.robustmq.mq9.*` |
| Rust | `robustmq` (crates.io) | `use robustmq::mq9::MQ9Client` |
| C# | `RobustMQ` (NuGet) | `using RobustMQ.Mq9` |

When new protocols are added (e.g. MQTT, Kafka), they live in sub-modules of the same package:
`robustmq.mqtt`, `@robustmq/sdk/mqtt`, `com.robustmq.mqtt`, `robustmq::mqtt`, etc.

The owner does not intervene in implementation details. Claude makes all technical decisions
and drives the project forward autonomously.
Expand All @@ -13,29 +44,31 @@ and drives the project forward autonomously.

## Version management

Source of truth: root `VERSION` file (currently `1.0.0`).
Source of truth: root `VERSION` file (currently `0.3.5`).

When bumping the version, update `VERSION` and all 6 build files in one commit:

- Python: `python/pyproject.toml` + `python/robustmq/__init__.py`
- Rust: `rust/Cargo.toml`
- Go: git tag only (e.g. `v1.0.0`) — no file to update
- Go: git tag only (e.g. `v0.3.5`) — no file to update
- JavaScript: `javascript/package.json`
- Java: `java/pom.xml`
- C#: `csharp/RobustMQ.Mq9/RobustMQ.Mq9.csproj`

Also update version references in `demo/`, `docs/`, and `README.md`.

---

## SDK implementation status

| Language | Package/Import | Class | NATS lib | Status |
| ---------- | ----------------- | ----------- | ------------ | -------------- |
| Python | `robustmq.mq9` | `MQ9Client` | `nats-py` | Implemented |
| Rust | `robustmq_mq9` | `MQ9Client` | `async-nats` | Scaffolded |
| Go | `mq9` (pkg) | `MQ9Client` | `nats.go` | Scaffolded |
| JavaScript | `@robustmq/mq9` | `MQ9Client` | `nats` v2 | Scaffolded |
| Java | `com.robustmq.mq9` | `MQ9Client` | `jnats` | Scaffolded |
| C# | `RobustMQ.Mq9` | `MQ9Client` | `NATS.Net` | Scaffolded |
| Language | Package/Import | Class | NATS lib | Status |
| ---------- | ----------------------- | ----------- | ------------ | -------------- |
| Python | `robustmq.mq9` | `MQ9Client` | `nats-py` | Implemented |
| Rust | `robustmq::mq9` | `MQ9Client` | `async-nats` | Scaffolded |
| Go | `mq9` (pkg) | `MQ9Client` | `nats.go` | Scaffolded |
| JavaScript | `@robustmq/sdk/mq9` | `MQ9Client` | `nats` v2 | Scaffolded |
| Java | `com.robustmq.mq9` | `MQ9Client` | `jnats` | Scaffolded |
| C# | `RobustMQ.Mq9` (ns) | `MQ9Client` | `NATS.Net` | Scaffolded |

Go constructor convention: `NewMQ9Client(...)` (struct, not class).

Expand All @@ -54,15 +87,23 @@ java/ # 🚧 Scaffolded only
csharp/ # 🚧 Scaffolded only
docs/
mq9-protocol.md # Authoritative protocol spec — read before implementing
demo/ # End-to-end demo scripts, one per language
demo/
demo-python/ # Standalone Python demo project
demo-go/ # Standalone Go demo project
demo-javascript/ # Standalone JavaScript demo project
demo-java/ # Standalone Java demo project (Maven)
demo-rust/ # Standalone Rust demo project
demo-csharp/ # Standalone C# demo project
```

---

## mq9 protocol

mq9 gives AI agents a durable mailbox. Messages persist until TTL expires; senders and
receivers do not need to be online simultaneously.
mq9 is RobustMQ's AI-native async communication protocol. It gives AI agents a durable mailbox —
messages persist until TTL expires; senders and receivers do not need to be online simultaneously.

Built on top of NATS (transport layer), mq9 adds store-first semantics and priority queuing.

### Subject structure

Expand Down Expand Up @@ -137,7 +178,7 @@ Return types:
### All languages

- NATS client is the only required runtime dependency
- Use `request/reply` for CREATE, LIST, DELETE, PUBLIC.LIST
- Use `request/reply` for CREATE, LIST, DELETE
- Use plain `publish` for SEND (no reply needed)
- Raise a typed `MQ9Error` (with `.code: int`) on server error responses
- Tests mock the NATS connection — no live server required
Expand Down Expand Up @@ -182,15 +223,14 @@ Return types:

## Demo module

Location: `demo/`
One script per language, all running the same scenario:
Location: `demo/`
Each language has a standalone project that imports the published SDK v0.3.5.

All demos run the same scenario:
1. Connect to `nats://localhost:4222`
2. Create a private mailbox (TTL 60s)
3. Send 3 messages (high / normal / low priority)
4. Subscribe and print received messages
5. List mailbox, delete one message
6. Create a public mailbox and discover it via PUBLIC.LIST
5. List mailbox metadata, delete one message
6. Create a public mailbox
7. Close connection

Demo scripts are standalone — they import the SDK from the local source tree, not a published package.
44 changes: 22 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,25 @@ Full spec: [docs/mq9-protocol.md](docs/mq9-protocol.md)

| Language | Package | Version | Install |
|----------|---------|---------|---------|
| Python | `robustmq-mq9` | 1.0.0 | `pip install robustmq-mq9` |
| Go | `github.com/robustmq/robustmq-sdk/go` | v1.0.0 | `go get github.com/robustmq/robustmq-sdk/go` |
| JavaScript | `@robustmq/mq9` | 1.0.0 | `npm install @robustmq/mq9` |
| Java | `com.robustmq:robustmq-sdk` | 1.0.0 | Maven / Gradle (see below) |
| Rust | `robustmq` | 1.0.0 | `cargo add robustmq` |
| C# | `RobustMQ.Mq9` | 1.0.0 | `dotnet add package RobustMQ.Mq9` |
| Python | `robustmq` | 0.3.5 | `pip install robustmq` |
| Go | `github.com/robustmq/robustmq-sdk/go` | v0.3.5 | `go get github.com/robustmq/robustmq-sdk/go` |
| JavaScript | `@robustmq/sdk` | 0.3.5 | `npm install @robustmq/sdk` |
| Java | `com.robustmq:robustmq` | 0.3.5 | Maven / Gradle (see below) |
| Rust | `robustmq` | 0.3.5 | `cargo add robustmq` |
| C# | `RobustMQ` | 0.3.5 | `dotnet add package RobustMQ` |

---

## Quick start

**Python**
```bash
pip install robustmq-mq9
pip install robustmq
```
```python
from robustmq.mq9 import Client, Priority

async with Client("nats://localhost:4222") as client:
async with Client("nats://demo.robustmq.com:4222") as client:
mailbox = await client.create(ttl=3600)
await client.send(mailbox.mail_id, b"hello", priority=Priority.NORMAL)

Expand All @@ -69,20 +69,20 @@ go get github.com/robustmq/robustmq-sdk/go
```go
import "github.com/robustmq/robustmq-sdk/go/mq9"

c := mq9.NewMQ9Client("nats://localhost:4222")
c := mq9.NewMQ9Client("nats://demo.robustmq.com:4222")
c.Connect()
mailbox, _ := c.Create(3600)
c.Send(mailbox.MailID, []byte("hello"), mq9.Normal)
```

**JavaScript / TypeScript**
```bash
npm install @robustmq/mq9
npm install @robustmq/sdk
```
```typescript
import { MQ9Client } from "@robustmq/mq9";
import { MQ9Client } from "@robustmq/sdk/mq9";

const client = new MQ9Client({ server: "nats://localhost:4222" });
const client = new MQ9Client({ server: "nats://demo.robustmq.com:4222" });
await client.connect();
const mailbox = await client.create({ ttl: 3600 });
await client.send(mailbox.mailId, "hello", "normal");
Expand All @@ -92,46 +92,46 @@ await client.send(mailbox.mailId, "hello", "normal");
```xml
<dependency>
<groupId>com.robustmq</groupId>
<artifactId>robustmq-sdk</artifactId>
<version>1.0.0</version>
<artifactId>robustmq</artifactId>
<version>0.3.5</version>
</dependency>
```
```java
import com.robustmq.mq9.*;

MQ9Client client = new MQ9Client("nats://localhost:4222");
MQ9Client client = new MQ9Client("nats://demo.robustmq.com:4222");
client.connect();
Mailbox mailbox = client.create(3600).get();
client.send(mailbox.getMailId(), "hello".getBytes(), Priority.NORMAL).get();
```

**Java (Gradle)**
```groovy
implementation 'com.robustmq:robustmq-sdk:1.0.0'
implementation 'com.robustmq:robustmq:0.3.5'
```

**Rust**
```toml
[dependencies]
robustmq = "1.0"
robustmq = "0.3"
tokio = { version = "1", features = ["full"] }
```
```rust
use robustmq::mq9::{MQ9Client, Priority};

let client = MQ9Client::connect("nats://localhost:4222").await?;
let client = MQ9Client::connect("nats://demo.robustmq.com:4222").await?;
let mailbox = client.create(3600, false, "", "").await?;
client.send(&mailbox.mail_id, b"hello", Priority::Normal).await?;
```

**C#**
```bash
dotnet add package RobustMQ.Mq9
dotnet add package RobustMQ
```
```csharp
using RobustMQ.Mq9;

await using var client = new MQ9Client("nats://localhost:4222");
await using var client = new MQ9Client("nats://demo.robustmq.com:4222");
await client.ConnectAsync();
var mailbox = await client.CreateAsync(3600);
await client.SendAsync(mailbox.MailId, "hello"u8.ToArray(), Priority.Normal);
Expand All @@ -154,7 +154,7 @@ await client.SendAsync(mailbox.MailId, "hello"u8.ToArray(), Priority.Normal);

## Running the demo

Each demo is a standalone project that connects to `nats://localhost:4222` and runs the same scenario:
Each demo is a standalone project that connects to `nats://demo.robustmq.com:4222` and runs the same scenario:
1. Create a private mailbox (TTL 60s)
2. Send 3 messages (high / normal / low priority)
3. Subscribe and print received messages
Expand Down Expand Up @@ -200,7 +200,7 @@ demo/
demo-java/ # Java standalone demo project (Maven)
demo-rust/ # Rust standalone demo project
demo-csharp/ # C# standalone demo project
VERSION # Canonical version (currently 1.0.0)
VERSION # Canonical version (currently 0.3.5)
```

---
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.0
0.3.5
9 changes: 4 additions & 5 deletions csharp/RobustMQ.Mq9/MQ9Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,20 +213,19 @@ private static Mq9Message ParseMessageNode(string mailId, JsonNode node)

file sealed class SubscriptionHandle : IAsyncDisposable
{
private readonly IDisposable _sub;
private readonly IAsyncDisposable _sub;
private readonly CancellationTokenSource _cts;

public SubscriptionHandle(IDisposable sub, CancellationTokenSource cts)
public SubscriptionHandle(IAsyncDisposable sub, CancellationTokenSource cts)
{
_sub = sub;
_cts = cts;
}

public ValueTask DisposeAsync()
public async ValueTask DisposeAsync()
{
_cts.Cancel();
_sub.Dispose();
await _sub.DisposeAsync();
_cts.Dispose();
return ValueTask.CompletedTask;
}
}
13 changes: 10 additions & 3 deletions csharp/RobustMQ.Mq9/RobustMQ.Mq9.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<PackageId>RobustMQ</PackageId>
<RootNamespace>RobustMQ.Mq9</RootNamespace>
<AssemblyName>RobustMQ.Mq9</AssemblyName>
<Version>1.0.0</Version>
<Description>RobustMQ C# SDK — mq9 AI-native async messaging</Description>
<AssemblyName>RobustMQ</AssemblyName>
<Version>0.3.5</Version>
<Description>RobustMQ SDK — unified messaging for AI, IoT, and data pipelines</Description>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NATS.Net" Version="2.*" />
</ItemGroup>

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>RobustMQ.Mq9.Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

</Project>
5 changes: 3 additions & 2 deletions demo/demo-csharp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* mq9 C# demo — connects to nats://localhost:4222 and runs the full scenario.
* mq9 C# demo — connects to nats://demo.robustmq.com:4222 and runs the full scenario.
*
* Run:
* cd demo/demo-csharp
Expand All @@ -9,7 +9,8 @@
using System.Text;
using RobustMQ.Mq9;

await using var client = new MQ9Client("nats://localhost:4222");
// demo.robustmq.com 是公共的 RobustMQ 服务,可用于验证功能和测试,也可修改为自己的服务地址。
await using var client = new MQ9Client("nats://demo.robustmq.com:4222");
await client.ConnectAsync();
Console.WriteLine("[csharp] connected");

Expand Down
2 changes: 1 addition & 1 deletion demo/demo-csharp/demo-csharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="RobustMQ.Mq9" Version="1.0.0" />
<PackageReference Include="RobustMQ.Mq9" Version="0.3.5" />
</ItemGroup>

</Project>
5 changes: 3 additions & 2 deletions demo/demo-go/main.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// mq9 Go demo — connects to nats://localhost:4222 and runs the full scenario.
// mq9 Go demo — connects to nats://demo.robustmq.com:4222 and runs the full scenario.
//
// Run:
//
Expand All @@ -15,7 +15,8 @@ import (
)

func main() {
c := mq9.NewMQ9Client("nats://localhost:4222")
// demo.robustmq.com 是公共的 RobustMQ 服务,可用于验证功能和测试,也可修改为自己的服务地址。
c := mq9.NewMQ9Client("nats://demo.robustmq.com:4222")
if err := c.Connect(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
Expand Down
6 changes: 3 additions & 3 deletions demo/demo-java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<groupId>io.robustmq.demo</groupId>
<artifactId>demo-java</artifactId>
<version>1.0.0</version>
<version>0.3.5</version>
<packaging>jar</packaging>

<name>RobustMQ mq9 Java Demo</name>
Expand All @@ -21,8 +21,8 @@
<dependencies>
<dependency>
<groupId>com.robustmq</groupId>
<artifactId>robustmq-sdk</artifactId>
<version>1.0.0</version>
<artifactId>robustmq</artifactId>
<version>0.3.5</version>
</dependency>
</dependencies>

Expand Down
Loading
Loading