feat: implement raft election and term state
This commit is contained in:
43
tests/NATS.Server.Tests/RaftElectionTests.cs
Normal file
43
tests/NATS.Server.Tests/RaftElectionTests.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using NATS.Server.Raft;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class RaftElectionTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Candidate_becomes_leader_after_majority_votes()
|
||||
{
|
||||
var cluster = RaftTestCluster.Create(3);
|
||||
var leader = await cluster.ElectLeaderAsync();
|
||||
|
||||
leader.Role.ShouldBe(RaftRole.Leader);
|
||||
leader.Term.ShouldBe(1);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class RaftTestCluster
|
||||
{
|
||||
public List<RaftNode> Nodes { get; }
|
||||
|
||||
private RaftTestCluster(List<RaftNode> nodes)
|
||||
{
|
||||
Nodes = nodes;
|
||||
}
|
||||
|
||||
public static RaftTestCluster Create(int nodes)
|
||||
{
|
||||
var created = Enumerable.Range(1, nodes).Select(i => new RaftNode($"n{i}")).ToList();
|
||||
return new RaftTestCluster(created);
|
||||
}
|
||||
|
||||
public Task<RaftNode> ElectLeaderAsync()
|
||||
{
|
||||
var candidate = Nodes[0];
|
||||
candidate.StartElection(Nodes.Count);
|
||||
|
||||
foreach (var voter in Nodes.Skip(1))
|
||||
candidate.ReceiveVote(voter.GrantVote(candidate.Term));
|
||||
|
||||
return Task.FromResult(candidate);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user