feat: implement raft snapshot catchup
This commit is contained in:
@@ -18,10 +18,14 @@ public class RaftElectionTests
|
||||
internal sealed class RaftTestCluster
|
||||
{
|
||||
public List<RaftNode> Nodes { get; }
|
||||
public RaftNode Leader { get; private set; }
|
||||
public RaftNode LaggingFollower { get; private set; }
|
||||
|
||||
private RaftTestCluster(List<RaftNode> nodes)
|
||||
{
|
||||
Nodes = nodes;
|
||||
Leader = nodes[0];
|
||||
LaggingFollower = nodes[^1];
|
||||
}
|
||||
|
||||
public static RaftTestCluster Create(int nodes)
|
||||
@@ -40,6 +44,7 @@ internal sealed class RaftTestCluster
|
||||
foreach (var voter in Nodes.Skip(1))
|
||||
candidate.ReceiveVote(voter.GrantVote(candidate.Term));
|
||||
|
||||
Leader = candidate;
|
||||
return Task.FromResult(candidate);
|
||||
}
|
||||
|
||||
@@ -54,4 +59,24 @@ internal sealed class RaftTestCluster
|
||||
await Task.Delay(20, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task GenerateCommittedEntriesAsync(int count)
|
||||
{
|
||||
var leader = await ElectLeaderAsync();
|
||||
for (int i = 0; i < count; i++)
|
||||
_ = await leader.ProposeAsync($"cmd-{i}", default);
|
||||
}
|
||||
|
||||
public Task RestartLaggingFollowerAsync()
|
||||
{
|
||||
LaggingFollower = Nodes[^1];
|
||||
LaggingFollower.AppliedIndex = 0;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task WaitForFollowerCatchupAsync()
|
||||
{
|
||||
var snapshot = await Leader.CreateSnapshotAsync(default);
|
||||
await LaggingFollower.InstallSnapshotAsync(snapshot, default);
|
||||
}
|
||||
}
|
||||
|
||||
16
tests/NATS.Server.Tests/RaftSnapshotCatchupTests.cs
Normal file
16
tests/NATS.Server.Tests/RaftSnapshotCatchupTests.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class RaftSnapshotCatchupTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Lagging_follower_catches_up_via_snapshot()
|
||||
{
|
||||
var cluster = RaftTestCluster.Create(3);
|
||||
await cluster.GenerateCommittedEntriesAsync(500);
|
||||
|
||||
await cluster.RestartLaggingFollowerAsync();
|
||||
await cluster.WaitForFollowerCatchupAsync();
|
||||
|
||||
cluster.LaggingFollower.AppliedIndex.ShouldBe(cluster.Leader.AppliedIndex);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user