feat: implement raft log replication and apply

This commit is contained in:
Joseph Doherty
2026-02-23 06:12:18 -05:00
parent 66ec378bdc
commit ecc4752c07
5 changed files with 113 additions and 4 deletions

View File

@@ -27,6 +27,8 @@ internal sealed class RaftTestCluster
public static RaftTestCluster Create(int nodes)
{
var created = Enumerable.Range(1, nodes).Select(i => new RaftNode($"n{i}")).ToList();
foreach (var node in created)
node.ConfigureCluster(created);
return new RaftTestCluster(created);
}
@@ -40,4 +42,16 @@ internal sealed class RaftTestCluster
return Task.FromResult(candidate);
}
public async Task WaitForAppliedAsync(long index)
{
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(2));
while (!timeout.IsCancellationRequested)
{
if (Nodes.All(n => n.AppliedIndex >= index))
return;
await Task.Delay(20, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
}
}
}

View File

@@ -0,0 +1,19 @@
using NATS.Server.Raft;
namespace NATS.Server.Tests;
public class RaftReplicationTests
{
[Fact]
public async Task Leader_replicates_entry_to_quorum_and_applies()
{
var cluster = RaftTestCluster.Create(3);
var leader = await cluster.ElectLeaderAsync();
var idx = await leader.ProposeAsync("create-stream", default);
idx.ShouldBeGreaterThan(0);
await cluster.WaitForAppliedAsync(idx);
cluster.Nodes.All(n => n.AppliedIndex >= idx).ShouldBeTrue();
}
}