Files
Joseph Doherty e553db6d40 docs: add Authentication, Clustering, JetStream, Monitoring overviews; update existing docs
New files:
- Documentation/Authentication/Overview.md — all 7 auth mechanisms with real source
  snippets (NKey/JWT/username-password/token/TLS mapping), nonce generation, account
  system, permissions, JWT permission templates
- Documentation/Clustering/Overview.md — route TCP handshake, in-process subscription
  propagation, gateway/leaf node stubs, honest gaps list
- Documentation/JetStream/Overview.md — API surface (4 handled subjects), streams,
  consumers, storage (MemStore/FileStore), in-process RAFT, mirror/source, gaps list
- Documentation/Monitoring/Overview.md — all 12 endpoints with real field tables,
  Go compatibility notes

Updated files:
- GettingStarted/Architecture.md — 14-subdirectory tree, real NatsClient/NatsServer
  field snippets, 9 new Go reference rows, Channel write queue design choice
- GettingStarted/Setup.md — xUnit 3, 100 test files grouped by area
- Operations/Overview.md — 99 test files, accurate Program.cs snippet, limitations
  section renamed to "Known Gaps vs Go Reference" with 7 real gaps
- Server/Overview.md — grouped fields, TLS/WS accept path, lame-duck mode, POSIX signals
- Configuration/Overview.md — 14 subsystem option tables, 24-row CLI table, LogOverrides
- Server/Client.md — Channel write queue, 4-task RunAsync, CommandMatrix, real fields

All docs verified against codebase 2026-02-23; 713 tests pass.
2026-02-23 10:14:18 -05:00

177 lines
7.5 KiB
Markdown

# Setup
This guide covers prerequisites, building, running, and testing the NATS .NET server.
## Prerequisites
### .NET 10 SDK
The project targets `net10.0` with `LangVersion preview` (configured in `Directory.Build.props`). Install the .NET 10 preview SDK from https://dotnet.microsoft.com/download.
Verify your installation:
```bash
dotnet --version
# Expected: 10.0.x
```
### Go Toolchain (optional)
The Go toolchain is only needed if you want to run the reference server from `golang/nats-server/` or execute Go test suites for cross-validation. It is not required for building or testing the .NET port.
```bash
go version
# Expected: go1.22 or later
```
---
## Building
The solution file uses the `.slnx` format (not `.sln`). Pass it explicitly if your tooling requires it.
```bash
# Build all projects
dotnet build
# Clean and rebuild
dotnet clean && dotnet build
```
The solution contains three projects:
| Project | Path |
|---------|------|
| `NATS.Server` | `src/NATS.Server/` |
| `NATS.Server.Host` | `src/NATS.Server.Host/` |
| `NATS.Server.Tests` | `tests/NATS.Server.Tests/` |
All projects share settings from `Directory.Build.props`: `net10.0` target framework, nullable reference types enabled, warnings treated as errors.
---
## Running
The server executable is `NATS.Server.Host`. With no arguments it binds to `0.0.0.0:4222`.
```bash
dotnet run --project src/NATS.Server.Host
```
### CLI Arguments
| Flag | Alias | Type | Default | Description |
|------|-------|------|---------|-------------|
| `-p` | `--port` | `int` | `4222` | TCP port to listen on |
| `-a` | `--addr` | `string` | `0.0.0.0` | Bind address |
| `-n` | `--name` | `string` | `nats-dotnet-<hostname>` | Server name reported in INFO |
```bash
# Custom port
dotnet run --project src/NATS.Server.Host -- -p 14222
# Custom address and name
dotnet run --project src/NATS.Server.Host -- -a 127.0.0.1 -p 4222 -n dev-server
```
The `--` separator is required to pass arguments through `dotnet run` to the application.
Startup log output (Serilog console sink):
```
[12:00:00 INF] Listening on 0.0.0.0:4222
```
---
## Testing
```bash
# 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~SubListTests"
```
### Test Stack
| Package | Version | Purpose |
|---------|---------|---------|
| `xunit` (xUnit 3) | 2.9.3 | Test framework |
| `xunit.runner.visualstudio` | 3.1.4 | VS/Rider test runner integration |
| `Shouldly` | 4.3.0 | Assertion library |
| `NSubstitute` | 5.3.0 | Mocking |
| `NATS.Client.Core` | 2.7.2 | Official NATS .NET client for integration tests |
| `coverlet.collector` | 6.0.4 | Code coverage |
Do not use FluentAssertions or Moq — the project uses Shouldly and NSubstitute exclusively.
### Test Files
The test project contains 100 test files organised by subsystem. Authentication and TLS tests cover token, username/password, NKey, JWT, and OCSP authenticators, account isolation, client permissions, TLS connection wrapping, and TLS rate limiting (`AuthProtocolTests.cs`, `AuthServiceTests.cs`, `AuthIntegrationTests.cs`, `AccountIsolationTests.cs`, `NKeyAuthenticatorTests.cs`, `JwtAuthenticatorTests.cs`, `TlsServerTests.cs`, `TlsHelperTests.cs`, `TlsConnectionWrapperTests.cs`, `TlsMapAuthenticatorTests.cs`, `TlsRateLimiterTests.cs`, and related files). JetStream and RAFT tests cover stream and consumer APIs, publish, pull and push consumers, ack and redelivery, retention policies, mirror/source replication, cluster reload, JWT limits, RAFT election, replication, and snapshot catchup (`JetStreamStreamApiTests.cs`, `JetStreamConsumerApiTests.cs`, `JetStreamPublishTests.cs`, `JetStreamPullConsumerTests.cs`, `JetStreamPushConsumerTests.cs`, `RaftElectionTests.cs`, `RaftReplicationTests.cs`, `RaftSnapshotCatchupTests.cs`, and related files). Clustering and routing tests cover route handshake, subscription propagation, gateway and leaf node bootstrap, cluster JetStream config, and response routing (`RouteHandshakeTests.cs`, `RouteSubscriptionPropagationTests.cs`, `GatewayLeafBootstrapTests.cs`, `ResponseRoutingTests.cs`). Monitoring and configuration tests cover config file parsing and reloading, options processing, monitoring endpoints, account stats, server stats, and subject-transform config (`MonitorTests.cs`, `NatsConfParserTests.cs`, `ConfigReloadTests.cs`, `ConfigProcessorTests.cs`, `SubjectTransformTests.cs`, and related files). WebSocket tests cover frame read/write, compression, upgrade handshake, origin checking, and integration (`WebSocket/WsFrameReadTests.cs`, `WebSocket/WsFrameWriterTests.cs`, `WebSocket/WsCompressionTests.cs`, `WebSocket/WsUpgradeTests.cs`, `WebSocket/WsIntegrationTests.cs`, and related files). Protocol and parser tests cover `NatsParser.TryParse` for each command type, header parsing, subject matching, and the `SubList` trie (`ParserTests.cs`, `NatsHeaderParserTests.cs`, `SubjectMatchTests.cs`, `SubListTests.cs`). Client lifecycle tests cover command dispatch, subscription tracking, write loop, verbose mode, no-responders, trace mode, client flags, and closed-reason handling (`ClientTests.cs`, `WriteLoopTests.cs`, `VerboseModeTests.cs`, `ClientFlagsTests.cs`, `ClientClosedReasonTests.cs`, and related files). Integration tests run end-to-end scenarios against a live server instance using `NATS.Client.Core` (`IntegrationTests.cs`, `AuthIntegrationTests.cs`, `NKeyIntegrationTests.cs`, `PermissionIntegrationTests.cs`, `SubjectTransformIntegrationTests.cs`, `ConfigIntegrationTests.cs`, `WebSocket/WsIntegrationTests.cs`).
---
## NuGet: Central Package Management
Package versions are defined centrally in `Directory.Packages.props`. Individual `.csproj` files reference packages without a `Version` attribute:
```xml
<!-- Directory.Packages.props -->
<PackageVersion Include="Shouldly" Version="4.3.0" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
```
```xml
<!-- NATS.Server.Tests.csproj -->
<PackageReference Include="Shouldly" />
<PackageReference Include="NSubstitute" />
```
To add a new dependency: add a `<PackageVersion>` entry in `Directory.Packages.props`, then add a `<PackageReference>` (without `Version`) in the relevant `.csproj`.
---
## Logging
The host configures Serilog via `Microsoft.Extensions.Logging` in `Program.cs`:
```csharp
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
.CreateLogger();
using var loggerFactory = new Serilog.Extensions.Logging.SerilogLoggerFactory(Log.Logger);
var server = new NatsServer(options, loggerFactory);
```
`NatsServer` and `NatsClient` receive `ILoggerFactory` and `ILogger` respectively via constructor injection. The core library (`NATS.Server`) depends only on `Microsoft.Extensions.Logging.Abstractions` — it has no direct Serilog dependency. The Serilog packages are wired in `NATS.Server.Host`.
Per-client loggers are created with a scoped category name that includes the client ID:
```csharp
var clientLogger = _loggerFactory.CreateLogger($"NATS.Server.NatsClient[{clientId}]");
```
To adjust log levels at runtime, modify the `LoggerConfiguration` in `Program.cs`.
---
## Related Documentation
- [Architecture](./Architecture.md)
- [Configuration Overview](../Configuration/Overview.md)
- [Protocol Overview](../Protocol/Overview.md)
- [Server Overview](../Server/Overview.md)
<!-- Last verified against codebase: 2026-02-23 -->