Files
natsdotnet/gaps/raft.md
2026-02-25 15:12:52 -05:00

31 KiB

RAFT — Gap Analysis

This file tracks what has and hasn't been ported from Go to .NET for the RAFT module. See stillmissing.md for the full LOC comparison across all modules.

LLM Instructions: How to Analyze This Category

Step 1: Read the Go Reference Files

Read each Go source file listed below. For every file:

  1. Extract all exported types (structs, interfaces, type aliases)
  2. Extract all exported methods on those types (receiver functions)
  3. Extract all exported standalone functions
  4. Note key constants, enums, and protocol states
  5. Note important unexported helpers that implement core logic (functions >20 lines)
  6. Pay attention to concurrency patterns (goroutines, mutexes, channels) — these map to different .NET patterns

Step 2: Read the .NET Implementation Files

Read all .cs files in the .NET directories listed below. For each Go symbol found in Step 1:

  1. Search for a matching type, method, or function in .NET
  2. If found, compare the behavior: does it handle the same edge cases? Same error paths?
  3. If partially implemented, note what's missing
  4. If not found, note it as MISSING

Step 3: Cross-Reference Tests

Compare Go test functions against .NET test methods:

  1. For each Go Test* function, check if a corresponding .NET [Fact] or [Theory] exists
  2. Note which test scenarios are covered and which are missing
  3. Check the parity DB (docs/test_parity.db) for existing mappings:
    sqlite3 docs/test_parity.db "SELECT go_test, dotnet_test, confidence FROM test_mappings tm JOIN go_tests gt ON tm.go_test_id=gt.rowid JOIN dotnet_tests dt ON tm.dotnet_test_id=dt.rowid WHERE gt.go_file LIKE '%PATTERN%'"
    

Step 4: Classify Each Item

Use these status values:

Status Meaning
PORTED Equivalent exists in .NET with matching behavior
PARTIAL .NET implementation exists but is incomplete (missing edge cases, error handling, or features)
MISSING No .NET equivalent found — needs to be ported
NOT_APPLICABLE Go-specific pattern that doesn't apply to .NET (build tags, platform-specific goroutine tricks, etc.)
DEFERRED Intentionally skipped for now (document why)

Step 5: Fill In the Gap Inventory

Add rows to the Gap Inventory table below. Group by Go source file. Include the Go file and line number so a porting LLM can jump directly to the reference implementation.

Key Porting Notes for RAFT

  • RAFT is used for JetStream cluster consensus — both meta-cluster (stream/consumer placement) and per-stream/consumer groups.
  • Key operations: leader election, log append/commit, snapshotting, peer management.
  • The .NET implementation (20 files, 3,045 LOC) is more granular than Go's single file. Check if the decomposition covers all RAFT states.

Go Reference Files (Source)

  • golang/nats-server/server/raft.go — RAFT consensus for clustered JetStream (~5,037 lines). Meta-cluster for metadata, per-stream/consumer RAFT groups. Leader election, log replication, snapshotting.

Go Reference Files (Tests)

  • golang/nats-server/server/raft_test.go
  • golang/nats-server/server/raft_helpers_test.go
  • golang/nats-server/server/raft_chain_of_blocks_helpers_test.go

.NET Implementation Files (Source)

  • src/NATS.Server/Raft/ (all 20 files)

.NET Implementation Files (Tests)

  • tests/NATS.Server.Tests/Raft/

Gap Inventory

golang/nats-server/server/raft.go — Exported Interfaces & Types

Go Symbol Go File:Line Status .NET Equivalent Notes
RaftNode (interface) raft.go:40-92 PARTIAL src/NATS.Server/Raft/IRaftNode.cs:5 Interface declared but empty — none of the 40+ methods from Go are defined
RaftNodeCheckpoint (interface) raft.go:98-103 PARTIAL src/NATS.Server/Raft/RaftSnapshotCheckpoint.cs:7 Chunk assembly exists but LoadLastSnapshot, AppendEntriesSeq, Abort, InstallSnapshot not matching Go's interface contract
WAL (interface) raft.go:105-118 PARTIAL src/NATS.Server/Raft/RaftWal.cs:20 .NET RaftWal is a concrete file-based WAL; does not implement Go's WAL interface (StoreMsg, LoadMsg, RemoveMsg, Compact, Purge, Truncate, State, FastState, Stop, Delete)
Peer (struct) raft.go:120-125 PARTIAL src/NATS.Server/Raft/RaftPeerState.cs:7 .NET has NextIndex/MatchIndex/LastContact/Active but missing Lag and Current fields from Go's Peer export
RaftState (enum) raft.go:127-135 PORTED src/NATS.Server/Raft/RaftState.cs:4 All four states: Follower, Leader, Candidate, Closed
RaftState.String() raft.go:137-149 MISSING No .NET ToString override for RaftState enum
RaftConfig (struct) raft.go:301-317 MISSING No equivalent configuration struct (Name, Store, Log, Track, Observer, Recovering, ScaleUp)
CommittedEntry (struct) raft.go:2506-2509 PARTIAL src/NATS.Server/Raft/CommitQueue.cs:9 CommitQueue exists as channel wrapper, but no CommittedEntry struct with Index+Entries
Entry (struct) raft.go:2641-2644 PARTIAL src/NATS.Server/Raft/RaftWireFormat.cs:73 RaftEntryWire has Type+Data but is wire-format only; no general Entry type used for proposals
EntryType (enum) raft.go:2605-2619 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:54-63 All types present including EntryCatchup (mapped as RaftEntryType)

golang/nats-server/server/raft.go — Exported RaftNode Interface Methods

Go Symbol Go File:Line Status .NET Equivalent Notes
Propose() raft.go:909-924 PARTIAL src/NATS.Server/Raft/RaftNode.cs:308 ProposeAsync exists but synchronous replication model, no write-error checking, no proposal queue
ProposeMulti() raft.go:928-945 MISSING No batch proposal support
ForwardProposal() raft.go:949-959 PARTIAL src/NATS.Server/Raft/NatsRaftTransport.cs:182 Transport has ForwardProposal but RaftNode does not call it automatically for non-leaders
InstallSnapshot() raft.go:1295-1311 PARTIAL src/NATS.Server/Raft/RaftNode.cs:699 InstallSnapshotAsync exists but no checkpointing, no WAL compaction, no highwayhash verification
CreateSnapshotCheckpoint() raft.go:1356-1360 PARTIAL src/NATS.Server/Raft/RaftNode.cs:519 CreateSnapshotCheckpointAsync exists but simplified — no async write, no WAL compaction tracking
SendSnapshot() raft.go:1284-1290 MISSING No direct snapshot send as append entry
NeedSnapshot() raft.go:1551-1555 MISSING No equivalent check
Applied() raft.go:1183-1185 MISSING No callback from upper layer for applied index tracking (delegates to Processed)
Processed() raft.go:1193-1240 PARTIAL src/NATS.Server/Raft/RaftNode.cs:664 MarkProcessed exists but much simpler — no aflr signaling, no leader state transition, no byte estimation
State() raft.go:2025-2027 PORTED src/NATS.Server/Raft/RaftNode.cs:43 Role property (uses RaftRole enum instead of RaftState)
Size() raft.go:2037-2043 MISSING No WAL size reporting
Progress() raft.go:2030-2034 MISSING No combined (index, commit, applied) return
Leader() raft.go:1712-1717 PORTED src/NATS.Server/Raft/RaftNode.cs:42 IsLeader property
LeaderSince() raft.go:1721-1726 MISSING No leader-since timestamp tracking
Quorum() raft.go:3070-3083 PARTIAL src/NATS.Server/Raft/RaftNode.cs:201 HasQuorum() exists but uses different window calculation (2x electionTimeout vs Go's lostQuorumInterval)
Current() raft.go:1840-1847 PARTIAL src/NATS.Server/Raft/RaftNode.cs:879 IsCurrent exists but no commit==applied check, no forward-progress polling
Healthy() raft.go:1850-1857 PARTIAL src/NATS.Server/Raft/RaftNode.cs:892 IsHealthy exists but different semantics — checks peer responsiveness, not isCurrent(true)
Term() raft.go:3119-3123 PORTED src/NATS.Server/Raft/RaftNode.cs:41 Term property
Leaderless() raft.go:1876-1883 MISSING No atomic hasleader flag
GroupLeader() raft.go:1865-1872 MISSING No leader ID tracking (only IsLeader bool)
HadPreviousLeader() raft.go:1860-1862 MISSING No pleader atomic flag
StepDown() raft.go:1900-1977 PARTIAL src/NATS.Server/Raft/RaftNode.cs:706 RequestStepDown exists but no preferred leader selection, no leader transfer, no EntryLeaderTransfer
SetObserver() raft.go:2394-2396 MISSING No observer mode
IsObserver() raft.go:2387-2391 MISSING No observer mode
Campaign() raft.go:1980-1984 PARTIAL src/NATS.Server/Raft/RaftNode.cs:771 CampaignImmediately exists but no random campaign timeout
CampaignImmediately() raft.go:1987-1993 PORTED src/NATS.Server/Raft/RaftNode.cs:771 CampaignImmediately()
ID() raft.go:2045-2051 PORTED src/NATS.Server/Raft/RaftNode.cs:40 Id property
Group() raft.go:2053-2056 MISSING No group name tracking
Peers() raft.go:2058-2077 PARTIAL src/NATS.Server/Raft/RaftNode.cs:872 GetPeerStates returns Dict but missing Lag calculation
ProposeKnownPeers() raft.go:2080-2089 MISSING No peer state broadcast
UpdateKnownPeers() raft.go:2092-2096 MISSING No peer state update
ProposeAddPeer() raft.go:962-983 PARTIAL src/NATS.Server/Raft/RaftNode.cs:372 ProposeAddPeerAsync exists but synchronous replication, no forwarding to leader
ProposeRemovePeer() raft.go:986-1019 PARTIAL src/NATS.Server/Raft/RaftNode.cs:415 ProposeRemovePeerAsync exists but no forwarding, no self-removal handling
MembershipChangeInProgress() raft.go:1021-1025 PORTED src/NATS.Server/Raft/RaftNode.cs:67 MembershipChangeInProgress property
AdjustClusterSize() raft.go:1059-1079 MISSING No cluster size adjustment
AdjustBootClusterSize() raft.go:1038-1055 MISSING No boot cluster size adjustment
ClusterSize() raft.go:1029-1033 MISSING No explicit cluster size property
ApplyQ() raft.go:2106 PARTIAL src/NATS.Server/Raft/RaftNode.cs:53 CommitQueue exists as Channel-based queue, different API than ipQueue
PauseApply() raft.go:1084-1092 MISSING No apply pausing
ResumeApply() raft.go:1111-1156 MISSING No apply resuming with replay
DrainAndReplaySnapshot() raft.go:1162-1177 PARTIAL src/NATS.Server/Raft/RaftNode.cs:537 DrainAndReplaySnapshotAsync exists but simplified — no catchup cancellation, no commit preservation
LeadChangeC() raft.go:2110 MISSING No leader change channel
QuitC() raft.go:2113 MISSING No quit channel
Created() raft.go:2115-2118 MISSING No creation timestamp
Stop() raft.go:2120-2122 MISSING No graceful shutdown (Dispose exists but minimal)
WaitForStop() raft.go:2124-2128 MISSING No wait-for-stop mechanism
Delete() raft.go:2130-2143 MISSING No delete with WAL cleanup
IsDeleted() raft.go:2145-2149 MISSING No deleted flag
RecreateInternalSubs() raft.go:658-747 MISSING No NATS internal subscription management
IsSystemAccount() raft.go:648-649 NOT_APPLICABLE .NET does not have system account NRG routing
GetTrafficAccountName() raft.go:652-656 NOT_APPLICABLE .NET does not have account NRG routing

golang/nats-server/server/raft.go — Core State Machine (unexported but critical)

Go Symbol Go File:Line Status .NET Equivalent Notes
raft (struct) raft.go:151-251 PARTIAL src/NATS.Server/Raft/RaftNode.cs:3 RaftNode has basic fields (term, vote, log, peers, commit) but missing: WAL, catchup state, progress map, pae cache, ipQueues, removed peers, many flags
run() raft.go:2275-2362 MISSING No main run loop / state machine goroutine
runAsFollower() raft.go:2441-2496 MISSING No follower state machine with select on channels
runAsCandidate() raft.go:3587-3670 MISSING No candidate state machine with vote collection
runAsLeader() raft.go:2951-3067 MISSING No leader state machine with heartbeat ticker and proposal batching
processAppendEntry() raft.go:3857-4248 MISSING Complex append entry processing with catchup, WAL alignment, truncation — not ported
processAppendEntryResponse() raft.go:4287-4339 MISSING No response processing with catchup triggering
processVoteRequest() raft.go:4780-4845 PARTIAL src/NATS.Server/Raft/RaftNode.cs:142 GrantVote handles basic vote logic but missing: log up-to-dateness check (lastTerm/lastIndex), catchup cancellation, campaign timeout reset
requestVote() raft.go:4856-4872 MISSING No vote request broadcast via RPC
handleAppendEntry() raft.go:3672-3684 MISSING No wire callback for append entries
handleAppendEntryResponse() raft.go:4342-4346 MISSING No wire callback for AE responses
handleVoteRequest() raft.go:4847-4854 MISSING No wire callback for vote requests
handleVoteResponse() raft.go:4764-4778 MISSING No wire callback for vote responses
handleForwardedProposal() raft.go:2854-2874 MISSING No forwarded proposal handler
handleForwardedRemovePeerProposal() raft.go:2820-2851 MISSING No forwarded remove-peer handler

golang/nats-server/server/raft.go — WAL & Storage

Go Symbol Go File:Line Status .NET Equivalent Notes
storeToWAL() raft.go:4360-4396 PARTIAL src/NATS.Server/Raft/RaftWal.cs:74 RaftWal.AppendAsync exists but different storage model (custom binary vs Go's filestore/memstore)
loadEntry() raft.go:3339-3346 MISSING No entry loading from WAL by index
loadFirstEntry() raft.go:3126-3130 MISSING No first-entry loading
truncateWAL() raft.go:3758-3815 MISSING No WAL truncation with snapshot invalidation
resetWAL() raft.go:3819-3821 MISSING No WAL reset
cachePendingEntry() raft.go:4449-4460 MISSING No pending append entry cache

golang/nats-server/server/raft.go — Snapshots

Go Symbol Go File:Line Status .NET Equivalent Notes
snapshot (struct) raft.go:1243-1248 PARTIAL src/NATS.Server/Raft/RaftSnapshot.cs:3 RaftSnapshot has LastIncludedIndex/Term/Data but missing peerstate encoding
encodeSnapshot() raft.go:1254-1279 MISSING No binary snapshot encoding with highwayhash
loadLastSnapshot() raft.go:1660-1707 MISSING No binary snapshot loading with hash verification
setupLastSnapshot() raft.go:1578-1656 MISSING No startup snapshot recovery from disk
installSnapshot() raft.go:1315-1350 PARTIAL src/NATS.Server/Raft/RaftNode.cs:699 InstallSnapshotAsync simplified — no WAL compact, no snapshot file management
termAndIndexFromSnapFile() raft.go:1564-1573 MISSING No snapshot filename parsing

golang/nats-server/server/raft.go — Peer & Membership State

Go Symbol Go File:Line Status .NET Equivalent Notes
peerState (struct) raft.go:4470-4474 MISSING No peer state struct with knownPeers/clusterSize/domainExt
encodePeerState() raft.go:4480-4492 MISSING No binary peer state encoding
decodePeerState() raft.go:4494-4514 MISSING No binary peer state decoding
writePeerState() raft.go:4603-4609 MISSING No peer state file persistence
readPeerState() raft.go:4611-4620 MISSING No peer state file reading
processPeerState() raft.go:4264-4282 MISSING No peer state processing from leader
addPeer() raft.go:2879-2898 PARTIAL src/NATS.Server/Raft/RaftNode.cs:129 AddMember exists but no cluster size/quorum adjustment, no removed-list reversal
removePeer() raft.go:2903-2913 PARTIAL src/NATS.Server/Raft/RaftNode.cs:131 RemoveMember exists but no removed tracking, no cluster size/quorum adjustment
adjustClusterSizeAndQuorum() raft.go:3534-3556 MISSING No dynamic cluster size/quorum recalculation
trackPeer() raft.go:3559-3585 MISSING No automatic peer tracking with add-on-discovery

golang/nats-server/server/raft.go — Elections & Voting

Go Symbol Go File:Line Status .NET Equivalent Notes
switchToFollower() raft.go:4958-4983 PARTIAL src/NATS.Server/Raft/RaftNode.cs:706 RequestStepDown sets Follower but missing: aflr reset, leaderState/leaderSince clear, acks reset, leader update
switchToCandidate() raft.go:4985-5014 PARTIAL src/NATS.Server/Raft/RaftNode.cs:133 StartElection increments term and votes but missing: observer/paused/processed checks, quorum loss signaling
switchToLeader() raft.go:5016-5037 PARTIAL src/NATS.Server/Raft/RaftNode.cs:986 TryBecomeLeader sets Role but missing: aflr setup, peer state broadcast, leader update
campaign() raft.go:2002-2009 PARTIAL src/NATS.Server/Raft/RaftNode.cs:971 CampaignWithPreVote starts election but no random timeout
wonElection() raft.go:4886-4888 PORTED src/NATS.Server/Raft/RaftNode.cs:986 Quorum check in TryBecomeLeader
selectNextLeader() raft.go:1887-1897 MISSING No next-leader selection by highest index
resetElectionTimeout() raft.go:2241-2243 PORTED src/NATS.Server/Raft/RaftNode.cs:737 ResetElectionTimeout with Timer
randElectionTimeout() raft.go:2235-2238 PORTED src/NATS.Server/Raft/RaftNode.cs:727 RandomizedElectionTimeout
randCampaignTimeout() raft.go:1995-1998 MISSING No separate campaign timeout

golang/nats-server/server/raft.go — Wire Format & RPC

Go Symbol Go File:Line Status .NET Equivalent Notes
voteRequest (struct) raft.go:4549-4556 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:84 RaftVoteRequestWire with Encode/Decode
voteResponse (struct) raft.go:4730-4735 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:132 RaftVoteResponseWire with Encode/Decode
appendEntry (struct) raft.go:2557-2569 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:189 RaftAppendEntryWire with Encode/Decode
appendEntryResponse (struct) raft.go:2760-2766 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:318 RaftAppendEntryResponseWire with Encode/Decode
ae.encode() raft.go:2662-2711 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:202 RaftAppendEntryWire.Encode()
decodeAppendEntry() raft.go:2714-2746 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:255 RaftAppendEntryWire.Decode()
vr.encode() (voteRequest) raft.go:4560-4568 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:94 RaftVoteRequestWire.Encode()
decodeVoteRequest() raft.go:4571-4583 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:109 RaftVoteRequestWire.Decode()
vr.encode() (voteResponse) raft.go:4739-4751 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:142 RaftVoteResponseWire.Encode()
decodeVoteResponse() raft.go:4753-4762 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:159 RaftVoteResponseWire.Decode()
ar.encode() raft.go:2777-2794 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:328 RaftAppendEntryResponseWire.Encode()
decodeAppendEntryResponse() raft.go:2799-2817 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:343 RaftAppendEntryResponseWire.Decode()
idLen constant raft.go:2756 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:23 RaftWireConstants.IdLen = 8
RaftWireHelpers (WriteId/ReadId) raft.go:2693,4581 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:561 RaftWireHelpers class
RaftWireHelpers (uvarint) raft.go:2682,2740 PORTED src/NATS.Server/Raft/RaftWireFormat.cs:597 WriteUvarint/ReadUvarint

golang/nats-server/server/raft.go — NATS Subjects & Transport

Go Symbol Go File:Line Status .NET Equivalent Notes
raftAllSubj constant raft.go:2162 PORTED src/NATS.Server/Raft/RaftSubjects.cs:16 RaftSubjects.All
raftVoteSubj constant raft.go:2163 PORTED src/NATS.Server/Raft/RaftSubjects.cs:22 RaftSubjects.Vote()
raftAppendSubj constant raft.go:2164 PORTED src/NATS.Server/Raft/RaftSubjects.cs:28 RaftSubjects.AppendEntry()
raftPropSubj constant raft.go:2165 PORTED src/NATS.Server/Raft/RaftSubjects.cs:34 RaftSubjects.Proposal()
raftRemovePeerSubj constant raft.go:2166 PORTED src/NATS.Server/Raft/RaftSubjects.cs:40 RaftSubjects.RemovePeer()
raftReply constant raft.go:2167 PORTED src/NATS.Server/Raft/RaftSubjects.cs:46 RaftSubjects.Reply()
raftCatchupReply constant raft.go:2168 PORTED src/NATS.Server/Raft/RaftSubjects.cs:52 RaftSubjects.CatchupReply()
sendRPC() raft.go:4874-4878 PARTIAL src/NATS.Server/Raft/NatsRaftTransport.cs:29 NatsRaftTransport._publish delegate, but no sendq integration
sendReply() raft.go:4880-4884 MISSING No reply sending via sendq
sendHeartbeat() raft.go:4545-4547 PARTIAL src/NATS.Server/Raft/NatsRaftTransport.cs:229 SendHeartbeatAsync exists but optimistic (no real ACK tracking)
IRaftTransport PORTED src/NATS.Server/Raft/RaftTransport.cs:3 Interface with AppendEntries, RequestVote, InstallSnapshot, SendTimeoutNow, SendHeartbeat
InMemoryRaftTransport PORTED src/NATS.Server/Raft/RaftTransport.cs:26 Full in-memory transport for testing
NatsRaftTransport PORTED src/NATS.Server/Raft/NatsRaftTransport.cs:18 Wire-level NATS transport with binary encoding
createInternalSubs() raft.go:2209-2233 MISSING No internal NATS subscription creation
subscribe() / unsubscribe() raft.go:2194-2206 MISSING No internal subscription management

golang/nats-server/server/raft.go — Catchup & Leader Coordination

Go Symbol Go File:Line Status .NET Equivalent Notes
catchupState (struct) raft.go:260-268 MISSING No catchup state tracking
runCatchup() raft.go:3132-3236 MISSING No catchup goroutine for lagging followers
catchupFollower() raft.go:3266-3337 MISSING No follower catchup initiation
createCatchup() raft.go:3718-3735 MISSING No catchup subscription/inbox creation
cancelCatchup() raft.go:3689-3697 MISSING No catchup cancellation
catchupStalled() raft.go:3702-3712 MISSING No stall detection
sendSnapshotToFollower() raft.go:3239-3264 MISSING No snapshot streaming to follower
sendCatchupSignal() raft.go:3738-3745 MISSING No catchup signal to upper layer
cancelCatchupSignal() raft.go:3748-3754 MISSING No catchup signal cancellation

golang/nats-server/server/raft.go — Commit & Apply

Go Symbol Go File:Line Status .NET Equivalent Notes
applyCommit() raft.go:3350-3462 MISSING Complex commit application with entry type dispatch, peer state processing, membership changes
tryCommit() raft.go:3468-3487 MISSING No quorum-based commit with ack counting
trackResponse() raft.go:3493-3529 MISSING No response tracking with ack map
sendMembershipChange() raft.go:2918-2949 MISSING No membership change send with WAL store

golang/nats-server/server/raft.go — Persistence & Term/Vote

Go Symbol Go File:Line Status .NET Equivalent Notes
writeTermVote() raft.go:4708-4727 PARTIAL src/NATS.Server/Raft/RaftNode.cs:993 PersistAsync writes meta.json (JSON) but Go uses binary tav.idx with dedup
readTermVote() raft.go:4637-4656 PARTIAL src/NATS.Server/Raft/RaftNode.cs:1013 LoadPersistedStateAsync reads meta.json but Go uses binary tav.idx
writePeerState() (on raft) raft.go:4589-4600 MISSING No binary peer state file writing
setWriteErr() / setWriteErrLocked() raft.go:4659-4704 MISSING No write error tracking with permission/space error escalation

golang/nats-server/server/raft.go — Server Integration

Go Symbol Go File:Line Status .NET Equivalent Notes
bootstrapRaftNode() raft.go:346-407 MISSING No raft bootstrap with peer validation and directory setup
initRaftNode() raft.go:410-614 MISSING No full raft initialization with WAL replay, snapshot recovery, peer state restore
startRaftNode() raft.go:617-628 MISSING No start-and-run goroutine
registerRaftNode() raft.go:776-783 MISSING No server-level raft registration
unregisterRaftNode() raft.go:786-792 MISSING No server-level raft unregistration
lookupRaftNode() raft.go:803-811 MISSING No raft node lookup by group
numRaftNodes() raft.go:795-799 MISSING No raft node count
stepdownRaftNodes() raft.go:831-851 MISSING No server-wide raft stepdown
shutdownRaftNodes() raft.go:856-875 MISSING No server-wide raft shutdown
transferRaftLeaders() raft.go:880-903 MISSING No server-wide leader transfer
reloadDebugRaftNodes() raft.go:815-827 NOT_APPLICABLE Debug flag reload is Go-specific
serverNameForNode() raft.go:759-763 NOT_APPLICABLE Server-level node mapping not yet needed
clusterNameForNode() raft.go:767-772 NOT_APPLICABLE Cluster-level node mapping not yet needed

golang/nats-server/server/raft.go — .NET Extensions (not in Go)

Go Symbol Go File:Line Status .NET Equivalent Notes
(none — .NET addition) PORTED src/NATS.Server/Raft/RaftWireFormat.cs:366 RaftPreVoteRequestWire — pre-vote wire format (Go does not have pre-vote)
(none — .NET addition) PORTED src/NATS.Server/Raft/RaftWireFormat.cs:410 RaftPreVoteResponseWire — pre-vote wire format
(none — .NET addition) PORTED src/NATS.Server/Raft/RaftWireFormat.cs:455 RaftTimeoutNowWire — leadership transfer wire format
(none — .NET addition) PORTED src/NATS.Server/Raft/RaftWireFormat.cs:508 RaftInstallSnapshotChunkWire — chunked snapshot wire format
(none — .NET addition) PORTED src/NATS.Server/Raft/CompactionPolicy.cs:9 CompactionPolicy / CompactionOptions — configurable log compaction
(none — .NET addition) PORTED src/NATS.Server/Raft/SnapshotChunkEnumerator.cs:16 SnapshotChunkEnumerator — snapshot chunking
(none — .NET addition) PORTED src/NATS.Server/Raft/RaftNode.cs:251 ReadIndexAsync — linearizable reads (Go does not expose this)
(none — .NET addition) PORTED src/NATS.Server/Raft/RaftNode.cs:464 Joint consensus (BeginJointConsensus/CommitJointConsensus)
(none — .NET addition) PORTED src/NATS.Server/Raft/RaftNode.cs:790 TransferLeadershipAsync with TimeoutNow RPC
(none — .NET addition) PORTED src/NATS.Server/Raft/RaftNode.cs:906 Pre-vote protocol (StartPreVote/RequestPreVote)

golang/nats-server/server/raft.go — Object Pools & Helpers

Go Symbol Go File:Line Status .NET Equivalent Notes
cePool / newCommittedEntry / ReturnToPool raft.go:2498-2532 NOT_APPLICABLE Go sync.Pool for CommittedEntry; .NET uses GC
entryPool / newEntry raft.go:2534-2547 NOT_APPLICABLE Go sync.Pool for Entry; .NET uses GC
aePool / newAppendEntry / returnToPool raft.go:2549-2583 NOT_APPLICABLE Go sync.Pool for appendEntry; .NET uses GC
pePool / newProposedEntry raft.go:2586-2603 NOT_APPLICABLE Go sync.Pool for proposedEntry; .NET uses GC
arPool / newAppendEntryResponse raft.go:2748-2775 NOT_APPLICABLE Go sync.Pool for appendEntryResponse; .NET uses GC
peers sync.Map (string interning) raft.go:2797 NOT_APPLICABLE Go-specific string interning optimization
debug() / warn() / error() raft.go:2364-2379 NOT_APPLICABLE Logging helpers — .NET uses ILogger
dios semaphore raft.go:1665-1667 NOT_APPLICABLE Go disk I/O semaphore — .NET uses async I/O
ipQueue usage raft.go:233-238 MISSING Go uses typed ipQueue channels for proposals, entries, votes, responses — .NET has no equivalent internal queue infrastructure

golang/nats-server/server/raft.go — Constants & Configuration

Go Symbol Go File:Line Status .NET Equivalent Notes
Election timeout defaults raft.go:277-287 PARTIAL src/NATS.Server/Raft/RaftNode.cs:56-57 .NET uses 150-300ms defaults; Go uses 4-9s defaults. Different design choice
hbInterval raft.go:283 MISSING No heartbeat interval constant
lostQuorumInterval raft.go:284 MISSING No lost quorum interval
observerModeInterval raft.go:286 MISSING No observer mode interval
peerRemoveTimeout raft.go:287 MISSING No peer remove timeout
Error sentinels raft.go:319-343 PARTIAL .NET uses InvalidOperationException instead of typed error sentinels
noLeader / noVote constants raft.go:4954-4956 MISSING No explicit no-leader/no-vote constants
paeDropThreshold / paeWarnThreshold raft.go:4399-4401 MISSING No pending append entry limits
maxBatch / maxEntries raft.go:3004-3005 MISSING No proposal batching thresholds
extensionState raft.go:4462-4468 MISSING No domain extension state tracking

Keeping This File Updated

After porting work is completed:

  1. Update status: Change MISSING → PORTED or PARTIAL → PORTED for each item completed
  2. Add .NET path: Fill in the ".NET Equivalent" column with the actual file:line
  3. Re-count LOC: Update the LOC numbers in stillmissing.md:
    # Re-count .NET source LOC for this module
    find src/NATS.Server/Raft/ -name '*.cs' -type f -exec cat {} + | wc -l
    # Re-count .NET test LOC for this module
    find tests/NATS.Server.Tests/Raft/ -name '*.cs' -type f -exec cat {} + | wc -l
    
  4. Add a changelog entry below with date and summary of what was ported
  5. Update the parity DB if new test mappings were created:
    sqlite3 docs/test_parity.db "INSERT INTO test_mappings (go_test_id, dotnet_test_id, confidence, notes) VALUES (?, ?, 'manual', 'ported in YYYY-MM-DD session')"
    

Change Log

Date Change By
2026-02-25 File created with LLM analysis instructions auto
2026-02-25 Full gap analysis completed: 196 items inventoried across 12 categories. Summary: 46 PORTED, 38 PARTIAL, 99 MISSING, 13 NOT_APPLICABLE, 0 DEFERRED. Wire format is well-ported; core state machine (run loop, catchup, WAL integration) is largely missing. claude-opus