Skip to content

Commit

Permalink
fixed bugs with multiple Members with same Address crashing `Clus…
Browse files Browse the repository at this point in the history
…terDaemon` (akkadotnet#7371)

close akkadotnet#7370
  • Loading branch information
Aaronontheweb authored Oct 30, 2024
1 parent 02157c3 commit 0cbddb5
Showing 1 changed file with 40 additions and 37 deletions.
77 changes: 40 additions & 37 deletions src/core/Akka.Cluster/ClusterDaemon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1635,22 +1635,22 @@ public void Welcome(Address joinWith, UniqueAddress from, Gossip gossip)
public void Leaving(Address address)
{
// only try to update if the node is available (in the member ring)
if (LatestGossip.Members.Any(m => m.Address.Equals(address) && m.Status is MemberStatus.Joining or MemberStatus.WeaklyUp or MemberStatus.Up))
foreach(var mem in LatestGossip.Members.Where(m => m.Address.Equals(address)))
{
// mark node as LEAVING
var newMembers = LatestGossip.Members.Select(m =>
if (mem.Status is MemberStatus.Joining or MemberStatus.WeaklyUp or MemberStatus.Up)
{
if (m.Address == address) return m.Copy(status: MemberStatus.Leaving);
return m;
}).ToImmutableSortedSet(); // mark node as LEAVING
var newGossip = LatestGossip.Copy(members: newMembers);

UpdateLatestGossip(newGossip);
// mark node as LEAVING
var newMembers = LatestGossip.Members
.Remove(mem).Add(mem.Copy(status: MemberStatus.Leaving));
var newGossip = LatestGossip.Copy(members: newMembers);
UpdateLatestGossip(newGossip);

_cluster.LogInfo("Marked address [{0}] as [{1}]", address, MemberStatus.Leaving);
PublishMembershipState();
// immediate gossip to speed up the leaving process
SendGossip();
_cluster.LogInfo("Marked address [{0}] as [{1}]", address, MemberStatus.Leaving);
PublishMembershipState();
// immediate gossip to speed up the leaving process
SendGossip();
}
}
}

Expand All @@ -1674,40 +1674,43 @@ public void Downing(Address address)
var localGossip = LatestGossip;
var localMembers = localGossip.Members;
var localOverview = localGossip.Overview;
var localSeen = localOverview.Seen;
var localReachability = _membershipState.DcReachability;

// check if the node to DOWN is in the 'members' set
var member = localMembers.FirstOrDefault(m => m.Address == address);
if (member != null && member.Status != MemberStatus.Down)
var found = false;
foreach (var member in localMembers.Where(m => m.Address == address))
{
if (localReachability.IsReachable(member.UniqueAddress))
_cluster.LogInfo("Marking node [{0}] as [{1}]", member.Address, MemberStatus.Down);
else
_cluster.LogInfo("Marking unreachable node [{0}] as [{1}]", member.Address, MemberStatus.Down);
found = true;
if (member.Status != MemberStatus.Down)
{
if (localReachability.IsReachable(member.UniqueAddress))
_cluster.LogInfo("Marking node [{0}] as [{1}]", member.Address, MemberStatus.Down);
else
_cluster.LogInfo("Marking unreachable node [{0}] as [{1}]", member.Address, MemberStatus.Down);


var newGossip = localGossip.MarkAsDown(member); //update gossip
UpdateLatestGossip(newGossip);
var newGossip = localGossip.MarkAsDown(member); //update gossip
UpdateLatestGossip(newGossip);

PublishMembershipState();
PublishMembershipState();

if (address == _cluster.SelfAddress)
{
// spread the word quickly, without waiting for next gossip tick
SendGossipRandom(MaxGossipsBeforeShuttingDownMyself);
}
else
{
// try to gossip immediately to downed node, as a STONITH signal
GossipTo(member.UniqueAddress);
if (address == _cluster.SelfAddress)
{
// spread the word quickly, without waiting for next gossip tick
SendGossipRandom(MaxGossipsBeforeShuttingDownMyself);
}
else
{
// try to gossip immediately to downed node, as a STONITH signal
GossipTo(member.UniqueAddress);
}
}

// if the previous statement did not evaluate to true, then this node is already being downed

}
else if (member != null)
{
// already down
}
else

if (!found)
{
_cluster.LogInfo("Ignoring down of unknown node [{0}]", address);
}
Expand Down

0 comments on commit 0cbddb5

Please sign in to comment.