Remove template UnitTest1.cs placeholder. Add actual project structure, run commands for the NATS server host, and update test command examples to reference the real project paths.
154 lines
8.1 KiB
Markdown
154 lines
8.1 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
This project ports the [NATS server](https://github.com/nats-io/nats-server) from Go to .NET 10 / C#. The Go reference implementation lives in `golang/nats-server/`. The .NET port lives at the repository root.
|
|
|
|
NATS is a high-performance publish-subscribe messaging system. It supports wildcards (`*` single token, `>` multi-token), queue groups for load balancing, request-reply, clustering (full-mesh routes, gateways, leaf nodes), and persistent streaming via JetStream.
|
|
|
|
## Build & Test Commands
|
|
|
|
The solution file is `NatsDotNet.slnx`.
|
|
|
|
```bash
|
|
# Build the solution
|
|
dotnet build
|
|
|
|
# Run all tests
|
|
dotnet test
|
|
|
|
# Run tests with verbose output
|
|
dotnet test -v normal
|
|
|
|
# Run a single test project
|
|
dotnet test tests/NATS.Server.Tests
|
|
|
|
# Run a specific test by name
|
|
dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~TestName"
|
|
|
|
# Run the NATS server (default port 4222)
|
|
dotnet run --project src/NATS.Server.Host
|
|
|
|
# Run the NATS server on a custom port
|
|
dotnet run --project src/NATS.Server.Host -- -p 14222
|
|
|
|
# Clean and rebuild
|
|
dotnet clean && dotnet build
|
|
```
|
|
|
|
## .NET Project Structure
|
|
|
|
```
|
|
NatsDotNet.slnx # Solution file
|
|
src/
|
|
NATS.Server/ # Core server library
|
|
NatsServer.cs # Server: listener, accept loop, shutdown
|
|
NatsClient.cs # Per-connection client: read/write loops, sub tracking
|
|
NatsOptions.cs # Server configuration (port, host, etc.)
|
|
Protocol/
|
|
NatsParser.cs # Protocol state machine (PUB, SUB, UNSUB, etc.)
|
|
NatsProtocol.cs # Wire-level protocol writing (INFO, MSG, PING/PONG)
|
|
Subscriptions/
|
|
SubjectMatch.cs # Subject validation and wildcard matching
|
|
SubList.cs # Trie-based subscription list with caching
|
|
SubListResult.cs # Match result container (plain subs + queue groups)
|
|
Subscription.cs # Subscription model (subject, sid, queue, client)
|
|
NATS.Server.Host/ # Executable host app
|
|
Program.cs # Entry point, CLI arg parsing (-p port)
|
|
tests/
|
|
NATS.Server.Tests/ # xUnit test project
|
|
ParserTests.cs # Protocol parser tests
|
|
SubjectMatchTests.cs # Subject validation & matching tests
|
|
SubListTests.cs # Subscription list trie tests
|
|
ClientTests.cs # Client-level protocol tests
|
|
ServerTests.cs # Server pubsub/wildcard tests
|
|
IntegrationTests.cs # End-to-end tests using NATS.Client.Core NuGet
|
|
```
|
|
|
|
## Go Reference Commands
|
|
|
|
```bash
|
|
# Build the Go reference server
|
|
cd golang/nats-server && go build
|
|
|
|
# Run Go tests for a specific area
|
|
cd golang/nats-server && go test -v -run TestName ./server/ -count=1 -timeout=30m
|
|
|
|
# Run all Go server tests (slow, ~30min)
|
|
cd golang/nats-server && go test -v ./server/ -count=1 -timeout=30m
|
|
```
|
|
|
|
## Architecture: NATS Server (Reference)
|
|
|
|
The Go source in `golang/nats-server/server/` is the authoritative reference. Key files by subsystem:
|
|
|
|
### Core Message Path
|
|
- **`server.go`** — Server struct, startup lifecycle (`NewServer` → `Run` → `WaitForShutdown`), listener management
|
|
- **`client.go`** (6700 lines) — Connection handling, `readLoop`/`writeLoop` goroutines, per-client subscription tracking, dynamic buffer sizing (512→65536 bytes), client types: `CLIENT`, `ROUTER`, `GATEWAY`, `LEAF`, `SYSTEM`
|
|
- **`parser.go`** — Protocol state machine. Text protocol: `PUB`, `SUB`, `UNSUB`, `CONNECT`, `INFO`, `PING/PONG`, `MSG`. Extended: `HPUB/HMSG` (headers), `RPUB/RMSG` (routes). Control line limit: 4096 bytes. Default max payload: 1MB.
|
|
- **`sublist.go`** — Trie-based subject matcher with wildcard support. Nodes have `psubs` (plain), `qsubs` (queue groups), special pointers for `*` and `>` wildcards. Results are cached with atomic generation IDs for invalidation.
|
|
|
|
### Authentication & Accounts
|
|
- **`auth.go`** — Auth mechanisms: username/password, token, NKeys (Ed25519), JWT, external auth callout, LDAP
|
|
- **`accounts.go`** (137KB) — Multi-tenant account isolation. Each account has its own `Sublist`, client set, and subject namespace. Supports exports/imports between accounts, service latency tracking.
|
|
- **`jwt.go`**, **`nkey.go`** — JWT claims parsing and NKey validation
|
|
|
|
### Clustering
|
|
- **`route.go`** — Full-mesh cluster routes. Route pooling (default 3 connections per peer). Account-specific dedicated routes. Protocol: `RS+`/`RS-` for subscribe propagation, `RMSG` for routed messages.
|
|
- **`gateway.go`** (103KB) — Inter-cluster bridges. Interest-only mode optimizes traffic. Reply subject mapping (`_GR_.` prefix) avoids cross-cluster conflicts.
|
|
- **`leafnode.go`** — Hub-and-spoke topology for edge deployments. Only subscribed subjects shared with hub. Loop detection via `$LDS.` prefix.
|
|
|
|
### JetStream (Persistence)
|
|
- **`jetstream.go`** — Orchestration, API subject handlers (`$JS.API.*`)
|
|
- **`stream.go`** (8000 lines) — Stream lifecycle, retention policies (Limits, Interest, WorkQueue), subject transforms, mirroring/sourcing
|
|
- **`consumer.go`** — Stateful readers. Push vs pull delivery. Ack policies: None, All, Explicit. Redelivery tracking, priority groups.
|
|
- **`filestore.go`** (337KB) — Block-based persistent storage with S2 compression, encryption (ChaCha20/AES-GCM), indexing
|
|
- **`memstore.go`** — In-memory storage with hash-wheel TTL expiration
|
|
- **`raft.go`** — RAFT consensus for clustered JetStream. Meta-cluster for metadata, per-stream/consumer RAFT groups.
|
|
|
|
### Configuration & Monitoring
|
|
- **`opts.go`** — CLI flags + config file loading. CLI overrides config. Supports hot reload on signal.
|
|
- **`monitor.go`** — HTTP endpoints: `/varz`, `/connz`, `/routez`, `/gatewayz`, `/jsz`, `/healthz`
|
|
- **`conf/`** — Config file parser (custom format with includes)
|
|
|
|
### Internal Data Structures
|
|
- **`server/avl/`** — AVL tree for sparse sequence sets (ack tracking)
|
|
- **`server/stree/`** — Subject tree for per-subject state in streams
|
|
- **`server/gsl/`** — Generic subject list, optimized trie
|
|
- **`server/thw/`** — Time hash wheel for efficient TTL expiration
|
|
|
|
## Key Porting Considerations
|
|
|
|
**Concurrency model:** Go uses goroutines (one per connection readLoop + writeLoop). Map to async/await with `Task`-based I/O. Use `Channel<T>` or `Pipe` for producer-consumer patterns where Go uses channels.
|
|
|
|
**Locking:** Go `sync.RWMutex` maps to `ReaderWriterLockSlim`. Go `sync.Map` maps to `ConcurrentDictionary`. Go `atomic` operations map to `Interlocked` or `volatile`.
|
|
|
|
**Subject matching:** The `Sublist` trie is performance-critical. Every published message triggers a `Match()` call. Cache invalidation uses atomic generation counters.
|
|
|
|
**Protocol parsing:** The parser is a byte-by-byte state machine. In .NET, use `System.IO.Pipelines` for zero-copy parsing with `ReadOnlySequence<byte>`.
|
|
|
|
**Buffer management:** Go uses `[]byte` slices with pooling. Map to `ArrayPool<byte>` and `Memory<T>`/`Span<T>`.
|
|
|
|
**Compression:** NATS uses S2 (Snappy variant) for route/gateway compression. Use an equivalent .NET S2 library or IronSnappy.
|
|
|
|
**Ports:** Client=4222, Cluster=6222, Monitoring=8222, Leaf=5222, Gateway=7222.
|
|
|
|
## Message Flow Summary
|
|
|
|
```
|
|
Client PUB → parser → permission check → Sublist.Match() →
|
|
├─ Local subscribers: MSG to each (queue subs: pick one per group)
|
|
├─ Cluster routes: RMSG to peers (who deliver to their locals)
|
|
├─ Gateways: forward to interested remote clusters
|
|
└─ JetStream: if subject matches a stream, store + deliver to consumers
|
|
```
|
|
|
|
## Conventions
|
|
|
|
- Reference the Go implementation file and line when porting a subsystem
|
|
- Maintain protocol compatibility — the .NET server must interoperate with existing NATS clients and Go servers in a cluster
|
|
- Use the same configuration file format as the Go server (parsed by `conf/` package)
|
|
- Match the Go server's monitoring JSON response shapes for tooling compatibility
|