From 4a0a12b8691569021ef947ae7bfe8c91c404fab0 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Thu, 18 Jul 2024 10:38:04 -0500 Subject: [PATCH 1/5] Removing `consider-app-version` --- .../Singleton/ClusterSingletonRestart3Spec.cs | 135 ------------------ .../Singleton/ClusterSingletonManager.cs | 4 +- .../ClusterSingletonManagerSettings.cs | 51 +------ .../Singleton/ClusterSingletonProxy.cs | 10 +- .../ClusterSingletonProxySettings.cs | 41 +----- .../Singleton/ClusterSingletonSettings.cs | 40 ++---- .../Singleton/MemberAgeOrdering.cs | 20 +-- .../Singleton/OldestChangedBuffer.cs | 13 +- .../Singleton/reference.conf | 5 - ...reAPISpec.ApproveCluster.Core.verified.txt | 1 - ...APISpec.ApproveCluster.DotNet.verified.txt | 1 - ...oreAPISpec.ApproveCluster.Net.verified.txt | 1 - ...Spec.ApproveClusterTools.Core.verified.txt | 11 +- ...ec.ApproveClusterTools.DotNet.verified.txt | 11 +- ...ISpec.ApproveClusterTools.Net.verified.txt | 11 +- .../Akka.Cluster/Properties/AssemblyInfo.cs | 1 - src/core/Akka/Util/AppVersion.cs | 8 +- 17 files changed, 47 insertions(+), 317 deletions(-) delete mode 100644 src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/ClusterSingletonRestart3Spec.cs diff --git a/src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/ClusterSingletonRestart3Spec.cs b/src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/ClusterSingletonRestart3Spec.cs deleted file mode 100644 index 0adbdaf5a02..00000000000 --- a/src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/ClusterSingletonRestart3Spec.cs +++ /dev/null @@ -1,135 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (C) 2009-2023 Lightbend Inc. -// Copyright (C) 2013-2023 .NET Foundation -// -//----------------------------------------------------------------------- - -using System; -using System.Collections.Immutable; -using System.Linq; -using System.Threading.Tasks; -using Akka.Actor; -using Akka.Cluster.Tools.Singleton; -using Akka.Configuration; -using Akka.TestKit; -using FluentAssertions; -using Xunit; -using Xunit.Abstractions; - -namespace Akka.Cluster.Tools.Tests.Singleton -{ - public class ClusterSingletonRestart3Spec : AkkaSpec - { - private readonly ActorSystem _sys1; - private readonly ActorSystem _sys2; - private readonly ActorSystem _sys3; - - public ClusterSingletonRestart3Spec(ITestOutputHelper output) : base(@" - akka.loglevel = DEBUG - akka.actor.provider = ""cluster"" - akka.cluster.app-version = ""1.0.0"" - #akka.cluster.auto-down-unreachable-after = 2s - akka.cluster.singleton.min-number-of-hand-over-retries = 5 - akka.cluster.singleton.consider-app-version = true - akka.remote { - dot-netty.tcp { - hostname = ""127.0.0.1"" - port = 0 - } - }", output) - { - _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\"") - .WithFallback(Sys.Settings.Config)); - InitializeLogger(_sys3); - } - - public void Join(ActorSystem from, ActorSystem to) - { - from.ActorOf(ClusterSingletonManager.Props(Props.Create(() => new Singleton()), - PoisonPill.Instance, - ClusterSingletonManagerSettings.Create(from)), "echo"); - - - Within(TimeSpan.FromSeconds(45), () => - { - AwaitAssert(() => - { - Cluster.Get(from).Join(Cluster.Get(to).SelfAddress); - Cluster.Get(from).State.Members.Select(x => x.UniqueAddress).Should().Contain(Cluster.Get(from).SelfUniqueAddress); - Cluster.Get(from) - .State.Members.Select(x => x.Status) - .ToImmutableHashSet() - .Should() - .Equal(ImmutableHashSet.Empty.Add(MemberStatus.Up)); - }); - }); - } - - [Fact] - public void Singleton_should_consider_AppVersion_when_handing_over() - { - Join(_sys1, _sys1); - Join(_sys2, _sys1); - - var proxy2 = _sys2.ActorOf( - ClusterSingletonProxy.Props("user/echo", ClusterSingletonProxySettings.Create(_sys2)), "proxy2"); - - Within(TimeSpan.FromSeconds(5), () => - { - AwaitAssert(() => - { - var probe = CreateTestProbe(_sys2); - proxy2.Tell("poke", probe.Ref); - var singleton = probe.ExpectMsg(TimeSpan.FromSeconds(1)); - singleton.Should().Be(Cluster.Get(_sys1).SelfMember); - singleton.AppVersion.Version.Should().Be("1.0.0"); - }); - }); - - // A new node with higher AppVersion joins the cluster - Join(_sys3, _sys1); - - // Old node with the singleton instance left the cluster - Cluster.Get(_sys1).Leave(Cluster.Get(_sys1).SelfAddress); - - // let it stabilize - Task.Delay(TimeSpan.FromSeconds(5)).Wait(); - - Within(TimeSpan.FromSeconds(10), () => - { - AwaitAssert(() => - { - var probe = CreateTestProbe(_sys2); - proxy2.Tell("poke", probe.Ref); - - // note that _sys3 has a higher app-version, so the singleton should start there - var singleton = probe.ExpectMsg(TimeSpan.FromSeconds(1)); - singleton.Should().Be(Cluster.Get(_sys3).SelfMember); - singleton.AppVersion.Version.Should().Be("1.0.2"); - }); - }); - } - - protected override void AfterAll() - { - base.AfterAll(); - Shutdown(_sys2); - Shutdown(_sys3); - } - - public class Singleton : ReceiveActor - { - public Singleton() - { - ReceiveAny(_ => - { - Sender.Tell(Cluster.Get(Context.System).SelfMember); - }); - } - } - } -} diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManager.cs b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManager.cs index c6d5c73528f..f58668df78a 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManager.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManager.cs @@ -880,9 +880,7 @@ private void InitializeFSM() { case StartOldestChangedBuffer _: { - _oldestChangedBuffer = Context.ActorOf( - Actor.Props.Create(() => new OldestChangedBuffer(_settings.Role, _settings.ConsiderAppVersion)) - .WithDispatcher(Context.Props.Dispatcher)); + _oldestChangedBuffer = Context.ActorOf(Actor.Props.Create(_settings.Role).WithDispatcher(Context.Props.Dispatcher)); GetNextOldestChanged(); return Stay(); } diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs index 0345b43a104..3ee008186be 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs @@ -57,8 +57,7 @@ public static ClusterSingletonManagerSettings Create(Config config) role: RoleOption(config.GetString("role")), removalMargin: TimeSpan.Zero, // defaults to ClusterSettings.DownRemovalMargin handOverRetryInterval: config.GetTimeSpan("hand-over-retry-interval"), - leaseSettings: lease, - considerAppVersion: config.GetBoolean("consider-app-version")); + leaseSettings: lease); } private static string RoleOption(string role) @@ -92,14 +91,6 @@ private static string RoleOption(string role) /// LeaseSettings for acquiring before creating the singleton actor /// public LeaseUsageSettings LeaseSettings { get; } - - - /// - /// Should be considered when the cluster singleton instance is being moved to another node. - /// When set to false, singleton instance will always be created on oldest member. - /// When set to true, singleton instance will be created on the oldest member with the highest number. - /// - public bool ConsiderAppVersion { get; } /// /// Creates a new instance of the . @@ -123,19 +114,9 @@ private static string RoleOption(string role) /// over has started or the previous oldest member is removed from the cluster /// (+ ). /// - /// - /// Should be considered when the cluster singleton instance is being moved to another node. - /// When set to false, singleton instance will always be created on oldest member. - /// When set to true, singleton instance will be created on the oldest member with the highest number. - /// /// TBD - public ClusterSingletonManagerSettings( - string singletonName, - string role, - TimeSpan removalMargin, - TimeSpan handOverRetryInterval, - bool considerAppVersion) - : this(singletonName, role, removalMargin, handOverRetryInterval, null, considerAppVersion) + public ClusterSingletonManagerSettings(string singletonName, string role, TimeSpan removalMargin, TimeSpan handOverRetryInterval) + : this(singletonName, role, removalMargin, handOverRetryInterval, null) { } @@ -162,19 +143,8 @@ public ClusterSingletonManagerSettings( /// (+ ). /// /// LeaseSettings for acquiring before creating the singleton actor - /// - /// Should be considered when the cluster singleton instance is being moved to another node. - /// When set to false, singleton instance will always be created on oldest member. - /// When set to true, singleton instance will be created on the oldest member with the highest number. - /// /// TBD - public ClusterSingletonManagerSettings( - string singletonName, - string role, - TimeSpan removalMargin, - TimeSpan handOverRetryInterval, - LeaseUsageSettings leaseSettings, - bool considerAppVersion) + public ClusterSingletonManagerSettings(string singletonName, string role, TimeSpan removalMargin, TimeSpan handOverRetryInterval, LeaseUsageSettings leaseSettings) { if (string.IsNullOrWhiteSpace(singletonName)) throw new ArgumentNullException(nameof(singletonName)); @@ -188,7 +158,6 @@ public ClusterSingletonManagerSettings( RemovalMargin = removalMargin; HandOverRetryInterval = handOverRetryInterval; LeaseSettings = leaseSettings; - ConsiderAppVersion = considerAppVersion; } /// @@ -241,21 +210,15 @@ public ClusterSingletonManagerSettings WithLeaseSettings(LeaseUsageSettings leas return Copy(leaseSettings: leaseSettings); } - private ClusterSingletonManagerSettings Copy( - string singletonName = null, - Option role = default, - TimeSpan? removalMargin = null, - TimeSpan? handOverRetryInterval = null, - Option leaseSettings = default, - bool? considerAppVersion = null) + private ClusterSingletonManagerSettings Copy(string singletonName = null, Option role = default, TimeSpan? removalMargin = null, + TimeSpan? handOverRetryInterval = null, Option leaseSettings = default) { return new ClusterSingletonManagerSettings( singletonName: singletonName ?? SingletonName, role: role.HasValue ? role.Value : Role, removalMargin: removalMargin ?? RemovalMargin, handOverRetryInterval: handOverRetryInterval ?? HandOverRetryInterval, - leaseSettings: leaseSettings.HasValue ? leaseSettings.Value : LeaseSettings, - considerAppVersion: considerAppVersion ?? ConsiderAppVersion + leaseSettings: leaseSettings.HasValue ? leaseSettings.Value : LeaseSettings ); } } diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxy.cs b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxy.cs index b624426555b..b321846910a 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxy.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxy.cs @@ -76,7 +76,6 @@ public static Props Props(string singletonManagerPath, ClusterSingletonProxySett .WithDeploy(Deploy.Local); } - private readonly MemberAgeOrdering _memberAgeComparer; private readonly ClusterSingletonProxySettings _settings; private readonly Cluster _cluster = Cluster.Get(Context.System); private readonly Queue> _buffer = new(); // queue seems to fit better @@ -85,7 +84,7 @@ public static Props Props(string singletonManagerPath, ClusterSingletonProxySett private string _identityId; private IActorRef _singleton = null; private ICancelable _identityTimer = null; - private ImmutableSortedSet _membersByAge; + private ImmutableSortedSet _membersByAge = ImmutableSortedSet.Empty.WithComparer(MemberAgeOrdering.Descending); private ILoggingAdapter _log; /// @@ -99,11 +98,6 @@ public ClusterSingletonProxy(string singletonManagerPath, ClusterSingletonProxyS _singletonPath = (singletonManagerPath + "/" + settings.SingletonName).Split('/'); _identityId = CreateIdentifyId(_identityCounter); - _memberAgeComparer = settings.ConsiderAppVersion - ? MemberAgeOrdering.DescendingWithAppVersion - : MemberAgeOrdering.Descending; - _membersByAge = ImmutableSortedSet.Empty.WithComparer(_memberAgeComparer); - Receive(s => HandleInitial(s)); Receive(m => Add(m.Member)); Receive(m => Remove(m.Member)); @@ -203,7 +197,7 @@ private void HandleInitial(ClusterEvent.CurrentClusterState state) TrackChanges(() => _membersByAge = state.Members .Where(m => m.Status == MemberStatus.Up && MatchingRole(m)) - .ToImmutableSortedSet(_memberAgeComparer)); + .ToImmutableSortedSet(MemberAgeOrdering.Descending)); } // Discard old singleton ActorRef and send a periodic message to self to identify the singleton. diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxySettings.cs b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxySettings.cs index 5e579de23f3..7b658d8551f 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxySettings.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxySettings.cs @@ -32,9 +32,7 @@ public static ClusterSingletonProxySettings Create(ActorSystem system) if (config.IsNullOrEmpty()) throw ConfigurationException.NullOrEmptyConfig("akka.cluster.singleton-proxy"); - var considerAppVersion = - system.Settings.Config.GetBoolean("akka.cluster.singleton.consider-app-version", false); - return Create(config, considerAppVersion); + return Create(config); } /// @@ -42,9 +40,8 @@ public static ClusterSingletonProxySettings Create(ActorSystem system) /// the default configuration `akka.cluster.singleton-proxy`. /// /// TBD - /// TBD /// TBD - public static ClusterSingletonProxySettings Create(Config config, bool considerAppVersion) + public static ClusterSingletonProxySettings Create(Config config) { if (config.IsNullOrEmpty()) throw ConfigurationException.NullOrEmptyConfig(); @@ -56,8 +53,7 @@ public static ClusterSingletonProxySettings Create(Config config, bool considerA singletonName: config.GetString("singleton-name"), role: role, singletonIdentificationInterval: config.GetTimeSpan("singleton-identification-interval"), - bufferSize: config.GetInt("buffer-size", 0), - considerAppVersion: considerAppVersion); + bufferSize: config.GetInt("buffer-size", 0)); } /// @@ -79,13 +75,6 @@ public static ClusterSingletonProxySettings Create(Config config, bool considerA /// If the location of the singleton is unknown the proxy will buffer this number of messages and deliver them when the singleton is identified. /// public int BufferSize { get; } - - /// - /// Should be considered when the cluster singleton instance is being moved to another node. - /// When set to false, singleton instance will always be created on oldest member. - /// When set to true, singleton instance will be created on the oldest member with the highest number. - /// - public bool ConsiderAppVersion { get; } /// /// Creates new instance of the . @@ -99,22 +88,12 @@ public static ClusterSingletonProxySettings Create(Config config, bool considerA /// are sent via the proxy. Use 0 to disable buffering, i.e.messages will be dropped immediately if the location /// of the singleton is unknown. /// - /// - /// Should be considered when the cluster singleton instance is being moved to another node. - /// When set to false, singleton instance will always be created on oldest member. - /// When set to true, singleton instance will be created on the oldest member with the highest number. - /// /// /// This exception is thrown when either the specified /// or is less than or equal to zero. /// /// - public ClusterSingletonProxySettings( - string singletonName, - string role, - TimeSpan singletonIdentificationInterval, - int bufferSize, - bool considerAppVersion) + public ClusterSingletonProxySettings(string singletonName, string role, TimeSpan singletonIdentificationInterval, int bufferSize) { if (string.IsNullOrEmpty(singletonName)) throw new ArgumentNullException(nameof(singletonName)); @@ -127,7 +106,6 @@ public ClusterSingletonProxySettings( Role = role; SingletonIdentificationInterval = singletonIdentificationInterval; BufferSize = bufferSize; - ConsiderAppVersion = considerAppVersion; } /// @@ -184,19 +162,14 @@ public ClusterSingletonProxySettings WithBufferSize(int bufferSize) return Copy(bufferSize: bufferSize); } - private ClusterSingletonProxySettings Copy( - string singletonName = null, - Option role = default, - TimeSpan? singletonIdentificationInterval = null, - int? bufferSize = null, - bool? considerAppVersion = null) + private ClusterSingletonProxySettings Copy(string singletonName = null, Option role = default, + TimeSpan? singletonIdentificationInterval = null, int? bufferSize = null) { return new ClusterSingletonProxySettings( singletonName: singletonName ?? SingletonName, role: role.HasValue ? role.Value : Role, singletonIdentificationInterval: singletonIdentificationInterval ?? SingletonIdentificationInterval, - bufferSize: bufferSize ?? BufferSize, - considerAppVersion: considerAppVersion ?? ConsiderAppVersion); + bufferSize: bufferSize ?? BufferSize); } } } diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonSettings.cs b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonSettings.cs index f70d9c061a2..d532106597e 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonSettings.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonSettings.cs @@ -56,13 +56,6 @@ public class ClusterSingletonSettings : INoSerializationVerificationNeeded /// LeaseSettings for acquiring before creating the singleton actor. /// public LeaseUsageSettings LeaseSettings { get; } - - /// - /// Should be considered when the cluster singleton instance is being moved to another node. - /// When set to false, singleton instance will always be created on oldest member. - /// When set to true, singleton instance will be created on the oldest member with the highest number. - /// - public bool ConsiderAppVersion { get; } /// /// Create settings from the default configuration `akka.cluster`. @@ -79,7 +72,7 @@ public static ClusterSingletonSettings Create(ActorSystem system) public static ClusterSingletonSettings Create(Config config) { var mgrSettings = ClusterSingletonManagerSettings.Create(config.GetConfig("singleton")); - var proxySettings = ClusterSingletonProxySettings.Create(config.GetConfig("singleton-proxy"), false); + var proxySettings = ClusterSingletonProxySettings.Create(config.GetConfig("singleton-proxy")); return new ClusterSingletonSettings( mgrSettings.Role, @@ -87,18 +80,10 @@ public static ClusterSingletonSettings Create(Config config) mgrSettings.RemovalMargin, mgrSettings.HandOverRetryInterval, proxySettings.BufferSize, - mgrSettings.LeaseSettings, - mgrSettings.ConsiderAppVersion); + mgrSettings.LeaseSettings); } - private ClusterSingletonSettings( - string role, - TimeSpan singletonIdentificationInterval, - TimeSpan removalMargin, - TimeSpan handOverRetryInterval, - int bufferSize, - LeaseUsageSettings leaseSettings, - bool considerAppVersion) + private ClusterSingletonSettings(string role, TimeSpan singletonIdentificationInterval, TimeSpan removalMargin, TimeSpan handOverRetryInterval, int bufferSize, LeaseUsageSettings leaseSettings) { if (singletonIdentificationInterval == TimeSpan.Zero) throw new ArgumentException("singletonIdentificationInterval must be positive", nameof(singletonIdentificationInterval)); @@ -118,7 +103,6 @@ private ClusterSingletonSettings( HandOverRetryInterval = handOverRetryInterval; BufferSize = bufferSize; LeaseSettings = leaseSettings; - ConsiderAppVersion = considerAppVersion; } public ClusterSingletonSettings WithRole(string role) => Copy(role: role); @@ -129,14 +113,7 @@ private ClusterSingletonSettings( public ClusterSingletonSettings WithLeaseSettings(LeaseUsageSettings leaseSettings) => Copy(leaseSettings: leaseSettings); - private ClusterSingletonSettings Copy( - Option role = default, - TimeSpan? singletonIdentificationInterval = null, - TimeSpan? removalMargin = null, - TimeSpan? handOverRetryInterval = null, - int? bufferSize = null, - Option leaseSettings = default, - bool? considerAppVersion = null) + private ClusterSingletonSettings Copy(Option role = default, TimeSpan? singletonIdentificationInterval = null, TimeSpan? removalMargin = null, TimeSpan? handOverRetryInterval = null, int? bufferSize = null, Option leaseSettings = default) { return new ClusterSingletonSettings( role: role.HasValue ? role.Value : Role, @@ -144,22 +121,21 @@ private ClusterSingletonSettings Copy( removalMargin: removalMargin ?? RemovalMargin, handOverRetryInterval: handOverRetryInterval ?? HandOverRetryInterval, bufferSize: bufferSize ?? BufferSize, - leaseSettings: leaseSettings.HasValue ? leaseSettings.Value : LeaseSettings, - considerAppVersion: considerAppVersion ?? ConsiderAppVersion); + leaseSettings: leaseSettings.HasValue ? leaseSettings.Value : LeaseSettings); } [InternalApi] internal ClusterSingletonManagerSettings ToManagerSettings(string singletonName) => - new(singletonName, Role, RemovalMargin, HandOverRetryInterval, LeaseSettings, ConsiderAppVersion); + new ClusterSingletonManagerSettings(singletonName, Role, RemovalMargin, HandOverRetryInterval, LeaseSettings); [InternalApi] internal ClusterSingletonProxySettings ToProxySettings(string singletonName) => - new(singletonName, Role, SingletonIdentificationInterval, BufferSize, ConsiderAppVersion); + new ClusterSingletonProxySettings(singletonName, Role, SingletonIdentificationInterval, BufferSize); [InternalApi] internal bool ShouldRunManager(Cluster cluster) => string.IsNullOrEmpty(Role) || cluster.SelfMember.Roles.Contains(Role); public override string ToString() => - $"ClusterSingletonSettings({Role}, {SingletonIdentificationInterval}, {RemovalMargin}, {HandOverRetryInterval}, {BufferSize}, {LeaseSettings}, {ConsiderAppVersion})"; + $"ClusterSingletonSettings({Role}, {SingletonIdentificationInterval}, {RemovalMargin}, {HandOverRetryInterval}, {BufferSize}, {LeaseSettings})"; } } diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/MemberAgeOrdering.cs b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/MemberAgeOrdering.cs index 420ca1b68c3..8db14e7151e 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/MemberAgeOrdering.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/MemberAgeOrdering.cs @@ -15,25 +15,15 @@ namespace Akka.Cluster.Tools.Singleton internal sealed class MemberAgeOrdering : IComparer { private readonly bool _ascending; - private readonly bool _considerAppVersion; - private MemberAgeOrdering(bool ascending, bool considerAppVersion) + private MemberAgeOrdering(bool ascending) { _ascending = ascending; - _considerAppVersion = considerAppVersion; } /// public int Compare(Member x, Member y) { - if (_considerAppVersion) - { - // 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; - } - if (x.Equals(y)) return 0; return x.IsOlderThan(y) ? (_ascending ? 1 : -1) @@ -43,15 +33,11 @@ public int Compare(Member x, Member y) /// /// TBD /// - public static readonly MemberAgeOrdering Ascending = new(true, false); - - public static readonly MemberAgeOrdering AscendingWithAppVersion = new(true, true); + public static readonly MemberAgeOrdering Ascending = new MemberAgeOrdering(true); /// /// TBD /// - public static readonly MemberAgeOrdering Descending = new(false, false); - - public static readonly MemberAgeOrdering DescendingWithAppVersion = new(false, true); + public static readonly MemberAgeOrdering Descending = new MemberAgeOrdering(false); } } diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/OldestChangedBuffer.cs b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/OldestChangedBuffer.cs index 7af3a3aeca4..0014cb97df9 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/OldestChangedBuffer.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/OldestChangedBuffer.cs @@ -92,22 +92,15 @@ public OldestChanged(UniqueAddress oldest) #endregion - private readonly MemberAgeOrdering _memberAgeComparer; private readonly CoordinatedShutdown _coordShutdown = CoordinatedShutdown.Get(Context.System); /// /// Creates a new instance of the . /// /// The role for which we're watching for membership changes. - /// Should cluster AppVersion be considered when sorting member age - public OldestChangedBuffer(string role, bool considerAppVersion) + public OldestChangedBuffer(string role) { _role = role; - _memberAgeComparer = considerAppVersion - ? MemberAgeOrdering.DescendingWithAppVersion - : MemberAgeOrdering.Descending; - _membersByAge = ImmutableSortedSet.Empty.WithComparer(_memberAgeComparer); - SetupCoordinatedShutdown(); } @@ -137,7 +130,7 @@ private void SetupCoordinatedShutdown() } private readonly string _role; - private ImmutableSortedSet _membersByAge; + private ImmutableSortedSet _membersByAge = ImmutableSortedSet.Empty.WithComparer(MemberAgeOrdering.Descending); private ImmutableQueue _changes = ImmutableQueue.Empty; private readonly Cluster _cluster = Cluster.Get(Context.System); @@ -163,7 +156,7 @@ private void HandleInitial(ClusterEvent.CurrentClusterState state) // all members except Joining and WeaklyUp _membersByAge = state.Members .Where(m => m.UpNumber != int.MaxValue && MatchingRole(m)) - .ToImmutableSortedSet(_memberAgeComparer); + .ToImmutableSortedSet(MemberAgeOrdering.Descending); // If there is some removal in progress of an older node it's not safe to immediately become oldest, // removal of younger nodes doesn't matter. Note that it can also be started via restart after diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/reference.conf b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/reference.conf index ea374bbffb5..7cc6aec748f 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/reference.conf +++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/reference.conf @@ -42,11 +42,6 @@ akka.cluster.singleton { # The interval between retries for acquiring the lease lease-retry-interval = 5s - - # Should akka.cluster.app-version be considered when the cluster singleton instance is being moved to another node - # When set to false, singleton instance will always be created on oldest member - # When set to true, singleton instance will be created on the oldest node with the highest member app-version number - consider-app-version = false } # //#singleton-config diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Core.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Core.verified.txt index 06124a13b85..42ad98fefa5 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Core.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Core.verified.txt @@ -9,7 +9,6 @@ [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tests.MultiNode")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tests.Performance")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tools")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tools.Tests")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tools.Tests.MultiNode")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.DistributedData")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Management.Cluster.Http")] diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.DotNet.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.DotNet.verified.txt index 38b3fc8834f..7f9b4127b53 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.DotNet.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.DotNet.verified.txt @@ -10,7 +10,6 @@ [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tests.MultiNode")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tests.Performance")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tools")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tools.Tests")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tools.Tests.MultiNode")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.DistributedData")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Management.Cluster.Http")] diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Net.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Net.verified.txt index f9aa7b26004..a8e1ccbd743 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Net.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCluster.Net.verified.txt @@ -10,7 +10,6 @@ [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tests.MultiNode")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tests.Performance")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tools")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tools.Tests")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Cluster.Tools.Tests.MultiNode")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.DistributedData")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("Akka.Management.Cluster.Http")] diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Core.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Core.verified.txt index 246186de841..d64b48f3408 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Core.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Core.verified.txt @@ -353,9 +353,8 @@ namespace Akka.Cluster.Tools.Singleton } public sealed class ClusterSingletonManagerSettings : Akka.Actor.INoSerializationVerificationNeeded { - public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, bool considerAppVersion) { } - public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings, bool considerAppVersion) { } - public bool ConsiderAppVersion { get; } + public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval) { } + public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings) { } public System.TimeSpan HandOverRetryInterval { get; } public Akka.Coordination.LeaseUsageSettings LeaseSettings { get; } public System.TimeSpan RemovalMargin { get; } @@ -384,14 +383,13 @@ namespace Akka.Cluster.Tools.Singleton } public sealed class ClusterSingletonProxySettings : Akka.Actor.INoSerializationVerificationNeeded { - public ClusterSingletonProxySettings(string singletonName, string role, System.TimeSpan singletonIdentificationInterval, int bufferSize, bool considerAppVersion) { } + public ClusterSingletonProxySettings(string singletonName, string role, System.TimeSpan singletonIdentificationInterval, int bufferSize) { } public int BufferSize { get; } - public bool ConsiderAppVersion { get; } public string Role { get; } public System.TimeSpan SingletonIdentificationInterval { get; } public string SingletonName { get; } public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Actor.ActorSystem system) { } - public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Configuration.Config config, bool considerAppVersion) { } + public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Configuration.Config config) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithBufferSize(int bufferSize) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithRole(string role) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithSingletonIdentificationInterval(System.TimeSpan singletonIdentificationInterval) { } @@ -400,7 +398,6 @@ namespace Akka.Cluster.Tools.Singleton public class ClusterSingletonSettings : Akka.Actor.INoSerializationVerificationNeeded { public int BufferSize { get; } - public bool ConsiderAppVersion { get; } public System.TimeSpan HandOverRetryInterval { get; } public Akka.Coordination.LeaseUsageSettings LeaseSettings { get; } public System.TimeSpan RemovalMargin { get; } diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt index be072a9fe12..0804dd96b5e 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt @@ -411,9 +411,8 @@ namespace Akka.Cluster.Tools.Singleton } public sealed class ClusterSingletonManagerSettings : Akka.Actor.INoSerializationVerificationNeeded { - public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, bool considerAppVersion) { } - public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings, bool considerAppVersion) { } - public bool ConsiderAppVersion { get; } + public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval) { } + public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings) { } public System.TimeSpan HandOverRetryInterval { get; } public Akka.Coordination.LeaseUsageSettings LeaseSettings { get; } public System.TimeSpan RemovalMargin { get; } @@ -442,14 +441,13 @@ namespace Akka.Cluster.Tools.Singleton } public sealed class ClusterSingletonProxySettings : Akka.Actor.INoSerializationVerificationNeeded { - public ClusterSingletonProxySettings(string singletonName, string role, System.TimeSpan singletonIdentificationInterval, int bufferSize, bool considerAppVersion) { } + public ClusterSingletonProxySettings(string singletonName, string role, System.TimeSpan singletonIdentificationInterval, int bufferSize) { } public int BufferSize { get; } - public bool ConsiderAppVersion { get; } public string Role { get; } public System.TimeSpan SingletonIdentificationInterval { get; } public string SingletonName { get; } public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Actor.ActorSystem system) { } - public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Configuration.Config config, bool considerAppVersion) { } + public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Configuration.Config config) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithBufferSize(int bufferSize) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithRole(string role) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithSingletonIdentificationInterval(System.TimeSpan singletonIdentificationInterval) { } @@ -458,7 +456,6 @@ namespace Akka.Cluster.Tools.Singleton public class ClusterSingletonSettings : Akka.Actor.INoSerializationVerificationNeeded { public int BufferSize { get; } - public bool ConsiderAppVersion { get; } public System.TimeSpan HandOverRetryInterval { get; } public Akka.Coordination.LeaseUsageSettings LeaseSettings { get; } public System.TimeSpan RemovalMargin { get; } diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt index 957381d1a55..541fc11f93c 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt @@ -411,9 +411,8 @@ namespace Akka.Cluster.Tools.Singleton } public sealed class ClusterSingletonManagerSettings : Akka.Actor.INoSerializationVerificationNeeded { - public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, bool considerAppVersion) { } - public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings, bool considerAppVersion) { } - public bool ConsiderAppVersion { get; } + public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval) { } + public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings) { } public System.TimeSpan HandOverRetryInterval { get; } public Akka.Coordination.LeaseUsageSettings LeaseSettings { get; } public System.TimeSpan RemovalMargin { get; } @@ -442,14 +441,13 @@ namespace Akka.Cluster.Tools.Singleton } public sealed class ClusterSingletonProxySettings : Akka.Actor.INoSerializationVerificationNeeded { - public ClusterSingletonProxySettings(string singletonName, string role, System.TimeSpan singletonIdentificationInterval, int bufferSize, bool considerAppVersion) { } + public ClusterSingletonProxySettings(string singletonName, string role, System.TimeSpan singletonIdentificationInterval, int bufferSize) { } public int BufferSize { get; } - public bool ConsiderAppVersion { get; } public string Role { get; } public System.TimeSpan SingletonIdentificationInterval { get; } public string SingletonName { get; } public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Actor.ActorSystem system) { } - public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Configuration.Config config, bool considerAppVersion) { } + public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Configuration.Config config) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithBufferSize(int bufferSize) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithRole(string role) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithSingletonIdentificationInterval(System.TimeSpan singletonIdentificationInterval) { } @@ -458,7 +456,6 @@ namespace Akka.Cluster.Tools.Singleton public class ClusterSingletonSettings : Akka.Actor.INoSerializationVerificationNeeded { public int BufferSize { get; } - public bool ConsiderAppVersion { get; } public System.TimeSpan HandOverRetryInterval { get; } public Akka.Coordination.LeaseUsageSettings LeaseSettings { get; } public System.TimeSpan RemovalMargin { get; } diff --git a/src/core/Akka.Cluster/Properties/AssemblyInfo.cs b/src/core/Akka.Cluster/Properties/AssemblyInfo.cs index b157afe7792..fe06dbf1041 100644 --- a/src/core/Akka.Cluster/Properties/AssemblyInfo.cs +++ b/src/core/Akka.Cluster/Properties/AssemblyInfo.cs @@ -17,7 +17,6 @@ [assembly: InternalsVisibleTo("Akka.Cluster.Tests.Performance")] [assembly: InternalsVisibleTo("Akka.Cluster.TestKit")] [assembly: InternalsVisibleTo("Akka.Cluster.Tools")] -[assembly: InternalsVisibleTo("Akka.Cluster.Tools.Tests")] [assembly: InternalsVisibleTo("Akka.Cluster.Tools.Tests.MultiNode")] [assembly: InternalsVisibleTo("Akka.Cluster.Sharding")] [assembly: InternalsVisibleTo("Akka.Cluster.Sharding.Tests")] diff --git a/src/core/Akka/Util/AppVersion.cs b/src/core/Akka/Util/AppVersion.cs index 32d19aebe11..6cc7c4f0fbe 100644 --- a/src/core/Akka/Util/AppVersion.cs +++ b/src/core/Akka/Util/AppVersion.cs @@ -208,7 +208,7 @@ private AppVersion Parse() public int CompareTo(AppVersion other) { - if (string.Equals(Version, other.Version, StringComparison.Ordinal)) // String equals without requiring parse + if (Version == other.Version) // String equals without requiring parse return 0; else { @@ -232,7 +232,7 @@ public int CompareTo(AppVersion other) if (other._rest == "" && _rest != "") diff = -1; else - diff = string.Compare(_rest, other._rest, StringComparison.Ordinal); + diff = _rest.CompareTo(other._rest); } } } @@ -243,12 +243,12 @@ public int CompareTo(AppVersion other) public bool Equals(AppVersion other) { - return other != null && string.Equals(Version, other.Version, StringComparison.Ordinal); + return other != null && Version == other.Version; } public override bool Equals(object obj) { - return obj is AppVersion av && Equals(av); + return base.Equals(obj as AppVersion); } public static bool operator ==(AppVersion first, AppVersion second) From eeda668463e5081350f1511ea9a59558ee009867 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Thu, 18 Jul 2024 10:46:29 -0500 Subject: [PATCH 2/5] removed `MemberAgeOrderingSpec` --- .../Singleton/MemberAgeOrderingSpec.cs | 89 ------------------- 1 file changed, 89 deletions(-) delete mode 100644 src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/MemberAgeOrderingSpec.cs diff --git a/src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/MemberAgeOrderingSpec.cs b/src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/MemberAgeOrderingSpec.cs deleted file mode 100644 index 5a3f603b868..00000000000 --- a/src/contrib/cluster/Akka.Cluster.Tools.Tests/Singleton/MemberAgeOrderingSpec.cs +++ /dev/null @@ -1,89 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (C) 2009-2023 Lightbend Inc. -// Copyright (C) 2013-2023 .NET Foundation -// -//----------------------------------------------------------------------- - -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Akka.Actor; -using Akka.Cluster.Tools.Singleton; -using Akka.Util; -using FluentAssertions; -using Xunit; - -namespace Akka.Cluster.Tools.Tests.Singleton -{ - public class MemberAgeOrderingSpec - { - [Fact(DisplayName = "MemberAgeOrdering should sort based on UpNumber")] - public void SortByUpNumberTest() - { - var members = new SortedSet(MemberAgeOrdering.DescendingWithAppVersion) - { - Create(Address.Parse("akka://sys@darkstar:1112"), upNumber: 3), - Create(Address.Parse("akka://sys@darkstar:1113"), upNumber: 1), - Create(Address.Parse("akka://sys@darkstar:1111"), upNumber: 9), - }; - - var seq = members.ToList(); - seq.Count.Should().Be(3); - seq[0].Should().Be(Create(Address.Parse("akka://sys@darkstar:1113"), upNumber: 1)); - seq[1].Should().Be(Create(Address.Parse("akka://sys@darkstar:1112"), upNumber: 3)); - seq[2].Should().Be(Create(Address.Parse("akka://sys@darkstar:1111"), upNumber: 9)); - } - - [Fact(DisplayName = "MemberAgeOrdering should sort based on Address if UpNumber is the same")] - public void SortByAddressTest() - { - var members = new SortedSet(MemberAgeOrdering.DescendingWithAppVersion) - { - Create(Address.Parse("akka://sys@darkstar:1112"), upNumber: 1), - Create(Address.Parse("akka://sys@darkstar:1113"), upNumber: 1), - Create(Address.Parse("akka://sys@darkstar:1111"), upNumber: 1), - }; - - var seq = members.ToList(); - seq.Count.Should().Be(3); - seq[0].Should().Be(Create(Address.Parse("akka://sys@darkstar:1111"), upNumber: 1)); - seq[1].Should().Be(Create(Address.Parse("akka://sys@darkstar:1112"), upNumber: 1)); - seq[2].Should().Be(Create(Address.Parse("akka://sys@darkstar:1113"), upNumber: 1)); - } - - [Fact(DisplayName = "MemberAgeOrdering should prefer AppVersion over UpNumber")] - public void SortByAppVersionTest() - { - var members = new SortedSet(MemberAgeOrdering.DescendingWithAppVersion) - { - 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:1111"), upNumber: 2, appVersion: AppVersion.Create("1.0.0")), - Create(Address.Parse("akka://sys@darkstar:1114"), upNumber: 7, appVersion: AppVersion.Create("1.0.2")), - Create(Address.Parse("akka://sys@darkstar:1115"), upNumber: 8, appVersion: AppVersion.Create("1.0.2")), - Create(Address.Parse("akka://sys@darkstar:1116"), upNumber: 6, appVersion: AppVersion.Create("1.0.2")), - }; - - var seq = members.ToList(); - seq.Count.Should().Be(6); - seq[0].Should().Be(Create(Address.Parse("akka://sys@darkstar:1116"), upNumber: 6, appVersion: AppVersion.Create("1.0.2"))); - seq[1].Should().Be(Create(Address.Parse("akka://sys@darkstar:1114"), upNumber: 7, appVersion: AppVersion.Create("1.0.2"))); - seq[2].Should().Be(Create(Address.Parse("akka://sys@darkstar:1115"), upNumber: 8, appVersion: AppVersion.Create("1.0.2"))); - seq[3].Should().Be(Create(Address.Parse("akka://sys@darkstar:1113"), upNumber: 1, appVersion: AppVersion.Create("1.0.0"))); - seq[4].Should().Be(Create(Address.Parse("akka://sys@darkstar:1111"), upNumber: 2, appVersion: AppVersion.Create("1.0.0"))); - seq[5].Should().Be(Create(Address.Parse("akka://sys@darkstar:1112"), upNumber: 3, appVersion: AppVersion.Create("1.0.0"))); - } - - public static Member Create( - Address address, - MemberStatus status = MemberStatus.Up, - ImmutableHashSet roles = null, - int uid = 0, - int upNumber = 0, - AppVersion appVersion = null) - { - return Member.Create(new UniqueAddress(address, uid), upNumber, status, roles ?? ImmutableHashSet.Empty, appVersion ?? AppVersion.Zero); - } - } -} From 0e27e029758f48f4ca49c51dd689a32a20fb71e0 Mon Sep 17 00:00:00 2001 From: Gregorius Soedharmo Date: Tue, 23 Jul 2024 04:20:30 +0700 Subject: [PATCH 3/5] Add backward compatibility constructors --- .../ClusterSingletonManagerSettings.cs | 41 +++++++++++++++++ .../ClusterSingletonProxySettings.cs | 44 +++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs index 3ee008186be..a0fb9145f59 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs @@ -92,6 +92,47 @@ private static string RoleOption(string role) /// public LeaseUsageSettings LeaseSettings { get; } + /// + /// Creates a new instance of the . + /// + /// The actor name of the child singleton actor. + /// + /// Singleton among the nodes tagged with specified role. If the role is not specified + /// it's a singleton among all nodes in the cluster. + /// + /// + /// Margin until the singleton instance that belonged to a downed/removed partition is + /// created in surviving partition. The purpose of this margin is that in case of + /// a network partition the singleton actors in the non-surviving partitions must + /// be stopped before corresponding actors are started somewhere else. + /// This is especially important for persistent actors. + /// + /// + /// When a node is becoming oldest it sends hand-over + /// request to previous oldest, that might be leaving the cluster. This is + /// retried with this interval until the previous oldest confirms that the hand + /// over has started or the previous oldest member is removed from the cluster + /// (+ ). + /// + /// LeaseSettings for acquiring before creating the singleton actor + /// + /// Should be considered when the cluster singleton instance is being moved to another node. + /// When set to false, singleton instance will always be created on oldest member. + /// When set to true, singleton instance will be created on the oldest member with the highest number. + /// + /// TBD + [Obsolete("considerAppVersion is not supported anymore, please use constructor that does not have the considerAppVersion argument. Since 1.5.27")] + public ClusterSingletonManagerSettings( + string singletonName, + string role, + TimeSpan removalMargin, + TimeSpan handOverRetryInterval, + LeaseUsageSettings leaseSettings, + bool considerAppVersion) + :this(singletonName, role, removalMargin, handOverRetryInterval, leaseSettings) + { + } + /// /// Creates a new instance of the . /// diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxySettings.cs b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxySettings.cs index 7b658d8551f..a56f3151114 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxySettings.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonProxySettings.cs @@ -35,6 +35,17 @@ public static ClusterSingletonProxySettings Create(ActorSystem system) return Create(config); } + /// + /// Create settings from a configuration with the same layout as + /// the default configuration `akka.cluster.singleton-proxy`. + /// + /// TBD + /// TBD + /// TBD + [Obsolete("considerAppVersion is not supported anymore, please use Create method that does not have the considerAppVersion argument. Since 1.5.27")] + public static ClusterSingletonProxySettings Create(Config config, bool considerAppVersion) + => Create(config); + /// /// Create settings from a configuration with the same layout as /// the default configuration `akka.cluster.singleton-proxy`. @@ -76,6 +87,39 @@ public static ClusterSingletonProxySettings Create(Config config) /// public int BufferSize { get; } + /// + /// Creates new instance of the . + /// + /// The actor name of the singleton actor that is started by the . + /// The role of the cluster nodes where the singleton can be deployed. If None, then any node will do. + /// Interval at which the proxy will try to resolve the singleton instance. + /// + /// If the location of the singleton is unknown the proxy will buffer this number of messages and deliver them + /// when the singleton is identified.When the buffer is full old messages will be dropped when new messages + /// are sent via the proxy. Use 0 to disable buffering, i.e.messages will be dropped immediately if the location + /// of the singleton is unknown. + /// + /// + /// Should be considered when the cluster singleton instance is being moved to another node. + /// When set to false, singleton instance will always be created on oldest member. + /// When set to true, singleton instance will be created on the oldest member with the highest number. + /// + /// + /// This exception is thrown when either the specified + /// or is less than or equal to zero. + /// + /// + [Obsolete("considerAppVersion is not supported anymore, please use constructor that does not have the considerAppVersion argument. Since 1.5.27")] + public ClusterSingletonProxySettings( + string singletonName, + string role, + TimeSpan singletonIdentificationInterval, + int bufferSize, + bool considerAppVersion) + : this(singletonName, role, singletonIdentificationInterval, bufferSize) + { + } + /// /// Creates new instance of the . /// From cb86a2d7182df3a485ce7443bd8be6c11e7a1043 Mon Sep 17 00:00:00 2001 From: Gregorius Soedharmo Date: Wed, 24 Jul 2024 04:55:23 +0700 Subject: [PATCH 4/5] Update API Approval list --- .../CoreAPISpec.ApproveClusterTools.DotNet.verified.txt | 9 +++++++++ .../CoreAPISpec.ApproveClusterTools.Net.verified.txt | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt index 0804dd96b5e..8647875c626 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt @@ -411,6 +411,9 @@ namespace Akka.Cluster.Tools.Singleton } public sealed class ClusterSingletonManagerSettings : Akka.Actor.INoSerializationVerificationNeeded { + [System.ObsoleteAttribute("considerAppVersion is not supported anymore, please use constructor that does not" + + " have the considerAppVersion argument. Since 1.5.27")] + public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings, bool considerAppVersion) { } public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval) { } public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings) { } public System.TimeSpan HandOverRetryInterval { get; } @@ -441,12 +444,18 @@ namespace Akka.Cluster.Tools.Singleton } public sealed class ClusterSingletonProxySettings : Akka.Actor.INoSerializationVerificationNeeded { + [System.ObsoleteAttribute("considerAppVersion is not supported anymore, please use constructor that does not" + + " have the considerAppVersion argument. Since 1.5.27")] + public ClusterSingletonProxySettings(string singletonName, string role, System.TimeSpan singletonIdentificationInterval, int bufferSize, bool considerAppVersion) { } public ClusterSingletonProxySettings(string singletonName, string role, System.TimeSpan singletonIdentificationInterval, int bufferSize) { } public int BufferSize { get; } public string Role { get; } public System.TimeSpan SingletonIdentificationInterval { get; } public string SingletonName { get; } public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Actor.ActorSystem system) { } + [System.ObsoleteAttribute("considerAppVersion is not supported anymore, please use Create method that does n" + + "ot have the considerAppVersion argument. Since 1.5.27")] + public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Configuration.Config config, bool considerAppVersion) { } public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Configuration.Config config) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithBufferSize(int bufferSize) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithRole(string role) { } diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt index 541fc11f93c..3e8f7b9c08a 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt @@ -411,6 +411,9 @@ namespace Akka.Cluster.Tools.Singleton } public sealed class ClusterSingletonManagerSettings : Akka.Actor.INoSerializationVerificationNeeded { + [System.ObsoleteAttribute("considerAppVersion is not supported anymore, please use constructor that does not" + + " have the considerAppVersion argument. Since 1.5.27")] + public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings, bool considerAppVersion) { } public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval) { } public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings) { } public System.TimeSpan HandOverRetryInterval { get; } @@ -441,12 +444,18 @@ namespace Akka.Cluster.Tools.Singleton } public sealed class ClusterSingletonProxySettings : Akka.Actor.INoSerializationVerificationNeeded { + [System.ObsoleteAttribute("considerAppVersion is not supported anymore, please use constructor that does not" + + " have the considerAppVersion argument. Since 1.5.27")] + public ClusterSingletonProxySettings(string singletonName, string role, System.TimeSpan singletonIdentificationInterval, int bufferSize, bool considerAppVersion) { } public ClusterSingletonProxySettings(string singletonName, string role, System.TimeSpan singletonIdentificationInterval, int bufferSize) { } public int BufferSize { get; } public string Role { get; } public System.TimeSpan SingletonIdentificationInterval { get; } public string SingletonName { get; } public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Actor.ActorSystem system) { } + [System.ObsoleteAttribute("considerAppVersion is not supported anymore, please use Create method that does n" + + "ot have the considerAppVersion argument. Since 1.5.27")] + public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Configuration.Config config, bool considerAppVersion) { } public static Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings Create(Akka.Configuration.Config config) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithBufferSize(int bufferSize) { } public Akka.Cluster.Tools.Singleton.ClusterSingletonProxySettings WithRole(string role) { } From 08751729fcb69c8c5abe09408d6cb5416e157982 Mon Sep 17 00:00:00 2001 From: Gregorius Soedharmo Date: Wed, 24 Jul 2024 05:48:20 +0700 Subject: [PATCH 5/5] Add missing backward compatibility ctor --- .../ClusterSingletonManagerSettings.cs | 42 ++++++++++++++++++- ...ec.ApproveClusterTools.DotNet.verified.txt | 3 ++ ...ISpec.ApproveClusterTools.Net.verified.txt | 3 ++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs index a0fb9145f59..8b4cd34ebae 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/Singleton/ClusterSingletonManagerSettings.cs @@ -129,10 +129,50 @@ public ClusterSingletonManagerSettings( TimeSpan handOverRetryInterval, LeaseUsageSettings leaseSettings, bool considerAppVersion) - :this(singletonName, role, removalMargin, handOverRetryInterval, leaseSettings) + : this(singletonName, role, removalMargin, handOverRetryInterval, leaseSettings) { } + /// + /// Creates a new instance of the . + /// + /// The actor name of the child singleton actor. + /// + /// Singleton among the nodes tagged with specified role. If the role is not specified + /// it's a singleton among all nodes in the cluster. + /// + /// + /// Margin until the singleton instance that belonged to a downed/removed partition is + /// created in surviving partition. The purpose of this margin is that in case of + /// a network partition the singleton actors in the non-surviving partitions must + /// be stopped before corresponding actors are started somewhere else. + /// This is especially important for persistent actors. + /// + /// + /// When a node is becoming oldest it sends hand-over + /// request to previous oldest, that might be leaving the cluster. This is + /// retried with this interval until the previous oldest confirms that the hand + /// over has started or the previous oldest member is removed from the cluster + /// (+ ). + /// + /// + /// Should be considered when the cluster singleton instance is being moved to another node. + /// When set to false, singleton instance will always be created on oldest member. + /// When set to true, singleton instance will be created on the oldest member with the highest number. + /// + /// TBD + [Obsolete("considerAppVersion is not supported anymore, please use constructor that does not have the considerAppVersion argument. Since 1.5.27")] + public ClusterSingletonManagerSettings( + string singletonName, + string role, + TimeSpan removalMargin, + TimeSpan handOverRetryInterval, + bool considerAppVersion) + : this(singletonName, role, removalMargin, handOverRetryInterval) + { + + } + /// /// Creates a new instance of the . /// diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt index 8647875c626..eba8a0d1f08 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.DotNet.verified.txt @@ -414,6 +414,9 @@ namespace Akka.Cluster.Tools.Singleton [System.ObsoleteAttribute("considerAppVersion is not supported anymore, please use constructor that does not" + " have the considerAppVersion argument. Since 1.5.27")] public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings, bool considerAppVersion) { } + [System.ObsoleteAttribute("considerAppVersion is not supported anymore, please use constructor that does not" + + " have the considerAppVersion argument. Since 1.5.27")] + public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, bool considerAppVersion) { } public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval) { } public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings) { } public System.TimeSpan HandOverRetryInterval { get; } diff --git a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt index 3e8f7b9c08a..cd304d4d27e 100644 --- a/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt +++ b/src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveClusterTools.Net.verified.txt @@ -414,6 +414,9 @@ namespace Akka.Cluster.Tools.Singleton [System.ObsoleteAttribute("considerAppVersion is not supported anymore, please use constructor that does not" + " have the considerAppVersion argument. Since 1.5.27")] public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings, bool considerAppVersion) { } + [System.ObsoleteAttribute("considerAppVersion is not supported anymore, please use constructor that does not" + + " have the considerAppVersion argument. Since 1.5.27")] + public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, bool considerAppVersion) { } public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval) { } public ClusterSingletonManagerSettings(string singletonName, string role, System.TimeSpan removalMargin, System.TimeSpan handOverRetryInterval, Akka.Coordination.LeaseUsageSettings leaseSettings) { } public System.TimeSpan HandOverRetryInterval { get; }