Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cluster singleton should consider Member AppVersion during hand over. #6065

Conversation

Arkatufus
Copy link
Contributor

@Arkatufus Arkatufus commented Aug 15, 2022

Fixes #6035

Changes

Changes the way oldest member sorting comparator works, taking Member.AppVersion into consideration. Members with higher AppVersion will always be bumped to the front of the list, regardless of Member age.

}

public override bool Equals(object obj)
{
return base.Equals(obj as AppVersion);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since AppVersion extends Object directly, base.Equals() does a direct reference equality, which is wrong.

// prefer nodes with the highest app version, even if they're younger
var appVersionDiff = x.AppVersion.CompareTo(y.AppVersion);
if (appVersionDiff != 0)
return _ascending ? appVersionDiff : appVersionDiff * -1;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AppVersion difference always wins compared to Member age difference

Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important design question

_sys1 = Sys;
_sys2 = ActorSystem.Create(Sys.Name, Sys.Settings.Config);
InitializeLogger(_sys2);
_sys3 = ActorSystem.Create(Sys.Name, ConfigurationFactory.ParseString("akka.cluster.app-version = \"1.0.2\"")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

// note that _sys3 has a higher app-version, so the singleton should start there
var singleton = probe.ExpectMsg<Member>(TimeSpan.FromSeconds(1));
singleton.Should().Be(Cluster.Get(_sys3).SelfMember);
singleton.AppVersion.Version.Should().Be("1.0.2");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -880,7 +880,9 @@ private void InitializeFSM()
{
case StartOldestChangedBuffer _:
{
_oldestChangedBuffer = Context.ActorOf(Actor.Props.Create<OldestChangedBuffer>(_settings.Role).WithDispatcher(Context.Props.Dispatcher));
_oldestChangedBuffer = Context.ActorOf(
Actor.Props.Create(() => new OldestChangedBuffer(_settings.Role, _settings.ConsiderAppVersion))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

{
// prefer nodes with the highest app version, even if they're younger
var appVersionDiff = x.AppVersion.CompareTo(y.AppVersion);
if (appVersionDiff != 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we have to run the sort in two phases here:

  1. AppVersion
  2. Age within the AppVersion cohort.

Looks to me like the sorter disregards age when AppVersion is considered - is that correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is correct, AppVersion always wins, we only consider member age if their AppVersion matches

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This design is wrong then - without the member age requirement there's no guarantee of stable singleton placement, which defeats the purpose of adding this feature (i.e. being able to predict the next location of where a singleton will be placed during a deployment)

We need to do the sort in multiple phases:

  1. Members by role
  2. Members within a role that have the highest app version
  3. Oldest member within the results of phase 2.

Let's design it to work that way.

Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to fix member ordering guarantee

{
Create(Address.Parse("akka://sys@darkstar:1112"), upNumber: 3, appVersion: AppVersion.Create("1.0.0")),
Create(Address.Parse("akka://sys@darkstar:1113"), upNumber: 1, appVersion: AppVersion.Create("1.0.0")),
Create(Address.Parse("akka://sys@darkstar:1116"), upNumber: 6, appVersion: AppVersion.Create("1.0.2")),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you humor me and add this item last on this list? That'd prove that the upnumber is canon, not insertion order.

Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Aaronontheweb
Copy link
Member

Aaronontheweb commented Aug 17, 2022

TODO: need to add changelog and website documentation for this feature

edit: in a new PR

@Aaronontheweb Aaronontheweb enabled auto-merge (squash) August 17, 2022 21:09
@Aaronontheweb
Copy link
Member

@Arkatufus API approvals are out of date

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants