- Update all 7 phase docs with source/target location references (golang/ for Go source, dotnet/ for .NET version) - Rename NATS.Server to ZB.MOM.NatsNet.Server in phase 4-7 docs - Update solution layout to dotnet/src/ and dotnet/tests/ structure - Create CLAUDE.md with project summary and phase links - Update .gitignore: track porting.db, add standard .NET patterns - Add golang/nats-server as git submodule - Add reports/generate-report.sh and pre-commit hook - Add documentation_rules.md to version control
194 lines
8.1 KiB
Markdown
194 lines
8.1 KiB
Markdown
# Phase 4: .NET Solution Design
|
|
|
|
Design the target .NET 10 solution structure and map every Go item to its .NET counterpart. This phase translates the Go codebase decomposition (from Phases 1-2) and library mappings (from Phase 3) into a concrete .NET implementation plan.
|
|
|
|
## Objective
|
|
|
|
Every module, feature, and test in the porting database must have either a .NET mapping (project, namespace, class, method) or a justified N/A status. The result is a complete blueprint for the porting work in Phase 6.
|
|
|
|
## Prerequisites
|
|
|
|
- Phases 1-3 complete: all Go items in the DB, all libraries mapped
|
|
- Verify with: `dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db`
|
|
|
|
## Source and Target Locations
|
|
|
|
- **Go source code** is located in the `golang/` folder (specifically `golang/nats-server/`)
|
|
- **.NET ported version** is located in the `dotnet/` folder
|
|
|
|
## Solution Structure
|
|
|
|
Define the .NET solution layout following standard conventions:
|
|
|
|
```
|
|
dotnet/
|
|
ZB.MOM.NatsNet.sln
|
|
src/
|
|
ZB.MOM.NatsNet.Server/ # Main server library (all core logic)
|
|
Protocol/ # Wire protocol parsing, commands
|
|
Subscriptions/ # SubList trie, subject matching
|
|
JetStream/ # Stream management, consumers
|
|
Cluster/ # Routes, gateways, leaf nodes
|
|
Auth/ # Authentication, accounts, JWT
|
|
...
|
|
ZB.MOM.NatsNet.Server.Host/ # Host/entry point (Program.cs, DI, config)
|
|
|
|
tests/
|
|
ZB.MOM.NatsNet.Server.Tests/ # Unit tests for ZB.MOM.NatsNet.Server
|
|
Protocol/
|
|
Subscriptions/
|
|
JetStream/
|
|
...
|
|
ZB.MOM.NatsNet.Server.IntegrationTests/ # Cross-module and end-to-end tests
|
|
```
|
|
|
|
The `ZB.MOM.NatsNet.Server` project holds all portable logic. `ZB.MOM.NatsNet.Server.Host` is the thin entry point that wires up dependency injection, configuration, and hosting. Tests mirror the source structure.
|
|
|
|
## Naming Conventions
|
|
|
|
Follow these rules consistently when mapping Go items to .NET:
|
|
|
|
| Aspect | Convention | Example |
|
|
|--------|-----------|---------|
|
|
| Classes | PascalCase | `NatsParser`, `SubList`, `JetStreamController` |
|
|
| Methods | PascalCase | `TryParse`, `Match`, `ProcessMessage` |
|
|
| Namespaces | `ZB.MOM.NatsNet.Server.[Module]` | `ZB.MOM.NatsNet.Server.Protocol`, `ZB.MOM.NatsNet.Server.Subscriptions` |
|
|
| Test classes | `[ClassName]Tests` | `NatsParserTests`, `SubListTests` |
|
|
| Test methods | `[Method]_[Scenario]_[Expected]` | `TryParse_ValidInput_ReturnsTrue` |
|
|
| Interfaces | `I[Name]` | `IMessageRouter`, `ISubListAccess` |
|
|
| Projects | `ZB.MOM.NatsNet.Server[.Suffix]` | `ZB.MOM.NatsNet.Server`, `ZB.MOM.NatsNet.Server.Host` |
|
|
|
|
Avoid abbreviations unless they are universally understood (e.g., `TCP`, `TLS`, `JWT`). Prefer descriptive names over short ones.
|
|
|
|
## Steps
|
|
|
|
### Step 1: Map modules
|
|
|
|
For each module in the database, assign a .NET project, namespace, and class. The `--namespace` and `--class` options are optional but recommended.
|
|
|
|
```bash
|
|
# List all modules to review
|
|
dotnet run --project tools/NatsNet.PortTracker -- module list --db porting.db
|
|
|
|
# Map a module to its .NET target
|
|
dotnet run --project tools/NatsNet.PortTracker -- module map <id> \
|
|
--project "ZB.MOM.NatsNet.Server" \
|
|
--namespace "ZB.MOM.NatsNet.Server.Protocol" \
|
|
--class "NatsParser" \
|
|
--db porting.db
|
|
```
|
|
|
|
Work through all modules systematically. Group related Go files into the same namespace:
|
|
|
|
| Go package/file pattern | .NET namespace |
|
|
|------------------------|----------------|
|
|
| `server/parser.go` | `ZB.MOM.NatsNet.Server.Protocol` |
|
|
| `server/sublist.go` | `ZB.MOM.NatsNet.Server.Subscriptions` |
|
|
| `server/jetstream*.go` | `ZB.MOM.NatsNet.Server.JetStream` |
|
|
| `server/route.go`, `server/gateway.go` | `ZB.MOM.NatsNet.Server.Cluster` |
|
|
| `server/auth.go`, `server/accounts.go` | `ZB.MOM.NatsNet.Server.Auth` |
|
|
| `server/pse/` | Likely N/A (Go-specific platform code) |
|
|
|
|
### Step 2: Map features
|
|
|
|
For each feature (function/method), assign the .NET class and method name:
|
|
|
|
```bash
|
|
# List features for a specific module
|
|
dotnet run --project tools/NatsNet.PortTracker -- feature list --module <module_id> --db porting.db
|
|
|
|
# Map a feature
|
|
dotnet run --project tools/NatsNet.PortTracker -- feature map <id> \
|
|
--project "ZB.MOM.NatsNet.Server" \
|
|
--class "NatsParser" \
|
|
--method "TryParse" \
|
|
--db porting.db
|
|
```
|
|
|
|
When mapping Go functions to .NET methods:
|
|
|
|
- Go free functions become static methods or instance methods on the appropriate class
|
|
- Go methods with receivers map to instance methods on the corresponding .NET class
|
|
- Go `init()` functions typically map to static constructors or initialization in DI setup
|
|
- Go `goroutine` launches map to `Task`-based async methods
|
|
|
|
### Step 3: Map tests
|
|
|
|
For each test function, assign the .NET test class and method:
|
|
|
|
```bash
|
|
# List tests for a module
|
|
dotnet run --project tools/NatsNet.PortTracker -- test list --module <module_id> --db porting.db
|
|
|
|
# Map a test
|
|
dotnet run --project tools/NatsNet.PortTracker -- test map <id> \
|
|
--project "ZB.MOM.NatsNet.Server.Tests" \
|
|
--class "NatsParserTests" \
|
|
--method "TryParse_ValidInput_ReturnsTrue" \
|
|
--db porting.db
|
|
```
|
|
|
|
Go test naming (`TestParserValid`) translates to .NET naming (`TryParse_ValidInput_ReturnsTrue`). Each Go `Test*` function maps to one or more `[Fact]` or `[Theory]` methods. Table-driven Go tests often become `[Theory]` with `[InlineData]` or `[MemberData]`.
|
|
|
|
### Step 4: Mark N/A items
|
|
|
|
Some Go code has no .NET equivalent. Mark these with a clear reason:
|
|
|
|
```bash
|
|
# Mark a module as N/A
|
|
dotnet run --project tools/NatsNet.PortTracker -- module set-na <id> \
|
|
--reason "Go-specific platform code, not needed in .NET" \
|
|
--db porting.db
|
|
|
|
# Mark a feature as N/A
|
|
dotnet run --project tools/NatsNet.PortTracker -- feature set-na <id> \
|
|
--reason "Go signal handling, replaced by .NET host lifecycle" \
|
|
--db porting.db
|
|
```
|
|
|
|
### Common N/A categories
|
|
|
|
Items that typically do not need a .NET port:
|
|
|
|
| Go item | Reason |
|
|
|---------|--------|
|
|
| `pse_darwin.go`, `pse_linux.go`, `pse_windows.go` | Go-specific platform syscall wrappers; use .NET `System.Diagnostics.Process` instead |
|
|
| `disk_avail_windows.go`, `disk_avail_linux.go` | Go-specific disk APIs; use .NET `System.IO.DriveInfo` instead |
|
|
| Custom logger (`logger.go`, `log.go`) | Replaced by Serilog via `ZB.MOM.NatsNet.Server.Host` |
|
|
| Signal handling (`signal.go`) | Replaced by .NET Generic Host `IHostLifetime` |
|
|
| Go `sync.Pool`, `sync.Map` wrappers | .NET has `ObjectPool<T>`, `ConcurrentDictionary<K,V>` built-in |
|
|
| Build tags / `_test.go` helpers specific to Go test infra | Replaced by xUnit attributes and test fixtures |
|
|
| `go:embed` directives | Replaced by embedded resources or `IFileProvider` |
|
|
|
|
Every N/A must include a reason. Bare N/A status without explanation is not acceptable.
|
|
|
|
## Verification
|
|
|
|
After mapping all items, run a quick check:
|
|
|
|
```bash
|
|
# Count unmapped items (should be 0)
|
|
dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
|
|
|
|
# Review all modules — every row should show DotNet Project filled or status n_a
|
|
dotnet run --project tools/NatsNet.PortTracker -- module list --db porting.db
|
|
|
|
# Review N/A items to confirm they all have reasons
|
|
dotnet run --project tools/NatsNet.PortTracker -- module list --status n_a --db porting.db
|
|
dotnet run --project tools/NatsNet.PortTracker -- feature list --status n_a --db porting.db
|
|
```
|
|
|
|
## Completion Criteria
|
|
|
|
- Every module has `dotnet_project` and `dotnet_namespace` set, or status is `n_a` with a reason
|
|
- Every feature has `dotnet_project`, `dotnet_class`, and `dotnet_method` set, or status is `n_a` with a reason
|
|
- Every test has `dotnet_project`, `dotnet_class`, and `dotnet_method` set, or status is `n_a` with a reason
|
|
- Naming follows PascalCase and the namespace hierarchy described above
|
|
- No two features map to the same class + method combination (collisions)
|
|
|
|
## Related Documentation
|
|
|
|
- [Phase 3: Library Mapping](phase-3-library-mapping.md) -- library mappings inform .NET class choices
|
|
- [Phase 5: Mapping Verification](phase-5-mapping-verification.md) -- next phase, validates all mappings
|
|
- [Phase 6: Porting](phase-6-porting.md) -- uses these mappings as the implementation blueprint
|