Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -191,17 +191,21 @@ public async Task ReplicaIdOffsetIsUpdatedWhenNodeIsAddedAndDeleted(Task<IFuncti
var watchdog2 = new ReplicaWatchdog(cluster2, functionStore, heartbeatFrequency: TimeSpan.FromHours(1), utcNow: () => DateTime.UtcNow, unhandledExceptionHandler: default(UnhandledExceptionHandler)!);
var watchdog3 = new ReplicaWatchdog(cluster3, functionStore, heartbeatFrequency: TimeSpan.FromHours(1), utcNow: () => DateTime.UtcNow, unhandledExceptionHandler: default(UnhandledExceptionHandler)!);

cluster3.IsLeader.ShouldBeFalse();
await watchdog3.Initialize();
cluster3.Offset.ShouldBe((ulong) 0);
cluster3.ReplicaCount.ShouldBe((ulong) 1);
cluster3.IsLeader.ShouldBeTrue();

await watchdog2.Initialize();
await watchdog3.PerformIteration(utcNowTicks: 0);
cluster3.Offset.ShouldBe((ulong) 1);
cluster3.ReplicaCount.ShouldBe((ulong) 2);
cluster2.Offset.ShouldBe((ulong) 0);
cluster2.ReplicaCount.ShouldBe((ulong) 2);

cluster3.IsLeader.ShouldBeFalse();
cluster2.IsLeader.ShouldBeTrue();

await watchdog1.Initialize();
await watchdog2.PerformIteration(utcNowTicks: 0);
await watchdog3.PerformIteration(utcNowTicks: 1);
Expand All @@ -211,6 +215,9 @@ public async Task ReplicaIdOffsetIsUpdatedWhenNodeIsAddedAndDeleted(Task<IFuncti
cluster2.ReplicaCount.ShouldBe((ulong) 3);
cluster1.Offset.ShouldBe((ulong) 0);
cluster1.ReplicaCount.ShouldBe((ulong) 3);
cluster3.IsLeader.ShouldBeFalse();
cluster2.IsLeader.ShouldBeFalse();
cluster1.IsLeader.ShouldBeTrue();

await store.Delete(cluster1.ReplicaId);
await watchdog3.PerformIteration(utcNowTicks: 1);
Expand All @@ -219,11 +226,14 @@ public async Task ReplicaIdOffsetIsUpdatedWhenNodeIsAddedAndDeleted(Task<IFuncti
cluster3.ReplicaCount.ShouldBe((ulong) 2);
cluster2.Offset.ShouldBe((ulong) 0);
cluster2.ReplicaCount.ShouldBe((ulong) 2);

cluster3.IsLeader.ShouldBeFalse();
cluster2.IsLeader.ShouldBeTrue();

await store.Delete(cluster2.ReplicaId);
await watchdog3.PerformIteration(utcNowTicks: 2);
cluster3.Offset.ShouldBe((ulong) 0);
cluster3.ReplicaCount.ShouldBe((ulong) 1);
cluster3.IsLeader.ShouldBeTrue();
}

public abstract Task ActiveReplicasDoNotDeleteEachOther();
Expand Down
10 changes: 10 additions & 0 deletions Core/Cleipnir.ResilientFunctions/Domain/ClusterInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ internal set
}
}

// The leader is the replica with the lowest id - i.e. the replica with offset 0 in the ascendingly ordered replica ids
public bool IsLeader
{
get
{
lock (_sync)
return _replicaCount > 0 && _offset == 0;
}
}

private readonly Lock _sync = new();

public bool OwnedByThisReplica(StoredId storedId)
Expand Down