From ddfe27f44c89e6a0f8f6c6a5cf12b57e3dd97f2b Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Thu, 26 May 2022 09:36:14 -0500 Subject: [PATCH] pass `Akka.Cluster.Cluster` into `IDowningProvider` directly close #5962 --- .../CoreAPISpec.ApproveCluster.verified.txt | 4 ++-- src/core/Akka.Cluster/Cluster.cs | 2 +- src/core/Akka.Cluster/Configuration/Cluster.conf | 4 +++- src/core/Akka.Cluster/DowningProvider.cs | 13 +++++++++---- src/core/Akka.Cluster/SBR/SplitBrainResolver.cs | 8 ++++---- .../SBR/SplitBrainResolverProvider.cs | 6 ++++-- src/core/Akka.Cluster/SplitBrainResolver.cs | 16 +++++++++------- 7 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.verified.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.verified.txt index da4d3dae1d1..fac1c6146cf 100644 --- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.verified.txt +++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.verified.txt @@ -272,7 +272,7 @@ namespace Akka.Cluster } public sealed class SplitBrainResolver : Akka.Cluster.IDowningProvider { - public SplitBrainResolver(Akka.Actor.ActorSystem system) { } + public SplitBrainResolver(Akka.Actor.ActorSystem system, Akka.Cluster.Cluster cluster) { } public System.TimeSpan DownRemovalMargin { get; } public Akka.Actor.Props DowningActorProps { get; } public System.TimeSpan StableAfter { get; } @@ -417,7 +417,7 @@ namespace Akka.Cluster.SBR } public class SplitBrainResolverProvider : Akka.Cluster.IDowningProvider { - public SplitBrainResolverProvider(Akka.Actor.ActorSystem system) { } + public SplitBrainResolverProvider(Akka.Actor.ActorSystem system, Akka.Cluster.Cluster cluster) { } public System.TimeSpan DownRemovalMargin { get; } public Akka.Actor.Props DowningActorProps { get; } } diff --git a/src/core/Akka.Cluster/Cluster.cs b/src/core/Akka.Cluster/Cluster.cs index c9c2d7dfbac..966a6bac633 100644 --- a/src/core/Akka.Cluster/Cluster.cs +++ b/src/core/Akka.Cluster/Cluster.cs @@ -132,7 +132,7 @@ public Cluster(ActorSystemImpl system) Scheduler = CreateScheduler(system); // it has to be lazy - otherwise if downing provider will init a cluster itself, it will deadlock - _downingProvider = new Lazy(() => Akka.Cluster.DowningProvider.Load(Settings.DowningProviderType, system), LazyThreadSafetyMode.ExecutionAndPublication); + _downingProvider = new Lazy(() => Akka.Cluster.DowningProvider.Load(Settings.DowningProviderType, system, this), LazyThreadSafetyMode.ExecutionAndPublication); //create supervisor for daemons under path "/system/cluster" _clusterDaemons = system.SystemActorOf(Props.Create(() => new ClusterDaemon(Settings)).WithDeploy(Deploy.Local), "cluster"); diff --git a/src/core/Akka.Cluster/Configuration/Cluster.conf b/src/core/Akka.Cluster/Configuration/Cluster.conf index ad7557168fa..64c0119d7a6 100644 --- a/src/core/Akka.Cluster/Configuration/Cluster.conf +++ b/src/core/Akka.Cluster/Configuration/Cluster.conf @@ -60,7 +60,9 @@ akka { # * if it is set to a duration the `AutoDowning` provider is with the configured downing duration # # If specified the value must be the fully qualified class name of a subclass of - # `akka.cluster.DowningProvider` having a public one argument constructor accepting an `ActorSystem` + # `akka.cluster.DowningProvider` having two argument constructor: + # - argument 1: accepting an `ActorSystem` + # - argument 2: accepting an `Akka.Cluster.Cluster` downing-provider-class = "" # If this is set to "off", the leader will not move 'Joining' members to 'Up' during a network diff --git a/src/core/Akka.Cluster/DowningProvider.cs b/src/core/Akka.Cluster/DowningProvider.cs index 9d5f374b7b5..0be58fc7f63 100644 --- a/src/core/Akka.Cluster/DowningProvider.cs +++ b/src/core/Akka.Cluster/DowningProvider.cs @@ -72,20 +72,25 @@ public NoDowning(ActorSystem system) internal static class DowningProvider { /// - /// TBD + /// Loads the from configuration and instantiates it via reflection. /// /// TBD /// TBD + /// The current cluster object. /// /// This exception is thrown when the specified does not implement . /// - /// TBD - public static IDowningProvider Load(Type downingProviderType, ActorSystem system) + /// The activated + /// + /// Required to pass in manually here since https://github.com/akkadotnet/akka.net/issues/5962 + /// can cause the SBR startup to fail when running with the `channel-executor`. + /// + public static IDowningProvider Load(Type downingProviderType, ActorSystem system, Cluster cluster) { var extendedSystem = system as ExtendedActorSystem; try { - return (IDowningProvider)Activator.CreateInstance(downingProviderType, extendedSystem); + return (IDowningProvider)Activator.CreateInstance(downingProviderType, extendedSystem, cluster); } catch (Exception e) { diff --git a/src/core/Akka.Cluster/SBR/SplitBrainResolver.cs b/src/core/Akka.Cluster/SBR/SplitBrainResolver.cs index 12c203e2cee..16ab1a6325c 100644 --- a/src/core/Akka.Cluster/SBR/SplitBrainResolver.cs +++ b/src/core/Akka.Cluster/SBR/SplitBrainResolver.cs @@ -27,22 +27,22 @@ internal class SplitBrainResolver : SplitBrainResolverBase { private Cluster _cluster; - public SplitBrainResolver(TimeSpan stableAfter, DowningStrategy strategy) + public SplitBrainResolver(TimeSpan stableAfter, DowningStrategy strategy, Cluster cluster) : base(stableAfter, strategy) { + _cluster = cluster; } public override UniqueAddress SelfUniqueAddress => _cluster.SelfUniqueAddress; - public static Props Props2(TimeSpan stableAfter, DowningStrategy strategy) + public static Props Props2(TimeSpan stableAfter, DowningStrategy strategy, Cluster cluster) { - return Props.Create(() => new SplitBrainResolver(stableAfter, strategy)); + return Props.Create(() => new SplitBrainResolver(stableAfter, strategy, cluster)); } // re-subscribe when restart protected override void PreStart() { - _cluster = Cluster.Get(Context.System); _cluster.Subscribe(Self, InitialStateAsEvents, typeof(IClusterDomainEvent)); base.PreStart(); diff --git a/src/core/Akka.Cluster/SBR/SplitBrainResolverProvider.cs b/src/core/Akka.Cluster/SBR/SplitBrainResolverProvider.cs index b1a809229c7..ea671410109 100644 --- a/src/core/Akka.Cluster/SBR/SplitBrainResolverProvider.cs +++ b/src/core/Akka.Cluster/SBR/SplitBrainResolverProvider.cs @@ -21,11 +21,13 @@ public class SplitBrainResolverProvider : IDowningProvider { private readonly SplitBrainResolverSettings _settings; private readonly ActorSystem _system; + private readonly Cluster _cluster; - public SplitBrainResolverProvider(ActorSystem system) + public SplitBrainResolverProvider(ActorSystem system, Cluster cluster) { _system = system; _settings = new SplitBrainResolverSettings(system.Settings.Config); + _cluster = cluster; } public TimeSpan DownRemovalMargin @@ -77,7 +79,7 @@ public Props DowningActorProps throw new InvalidOperationException(); } - return SplitBrainResolver.Props2(_settings.DowningStableAfter, strategy); + return SplitBrainResolver.Props2(_settings.DowningStableAfter, strategy, _cluster); } } } diff --git a/src/core/Akka.Cluster/SplitBrainResolver.cs b/src/core/Akka.Cluster/SplitBrainResolver.cs index 0eb10106828..922e5f61fc3 100644 --- a/src/core/Akka.Cluster/SplitBrainResolver.cs +++ b/src/core/Akka.Cluster/SplitBrainResolver.cs @@ -18,8 +18,9 @@ namespace Akka.Cluster public sealed class SplitBrainResolver : IDowningProvider { private readonly ActorSystem _system; + private readonly Cluster _cluster; - public SplitBrainResolver(ActorSystem system) + public SplitBrainResolver(ActorSystem system, Cluster cluster) { _system = system; var config = system.Settings.Config.GetConfig("akka.cluster.split-brain-resolver"); @@ -28,11 +29,12 @@ public SplitBrainResolver(ActorSystem system) StableAfter = config.GetTimeSpan("stable-after", null); Strategy = ResolveSplitBrainStrategy(config); + _cluster = cluster; } public TimeSpan DownRemovalMargin => Cluster.Get(_system).Settings.DownRemovalMargin; public TimeSpan StableAfter { get; } - public Props DowningActorProps => SplitBrainDecider.Props(StableAfter, Strategy); + public Props DowningActorProps => SplitBrainDecider.Props(StableAfter, Strategy, _cluster); internal ISplitBrainStrategy Strategy { get; } @@ -176,7 +178,7 @@ public IEnumerable Apply(NetworkPartitionContext context) if (remaining.IsEmpty && unreachable.IsEmpty) // prevent exception due to both lists being empty { - return new Member[0]; + return Array.Empty(); } var oldest = remaining.Union(unreachable).ToImmutableSortedSet(Member.AgeOrdering).First(); @@ -241,8 +243,8 @@ private sealed class StabilityReached #endregion - public static Actor.Props Props(TimeSpan stableAfter, ISplitBrainStrategy strategy) => - Actor.Props.Create(() => new SplitBrainDecider(stableAfter, strategy)).WithDeploy(Deploy.Local); + public static Actor.Props Props(TimeSpan stableAfter, ISplitBrainStrategy strategy, Cluster cluster) => + Actor.Props.Create(() => new SplitBrainDecider(stableAfter, strategy, cluster)).WithDeploy(Deploy.Local); private readonly Cluster _cluster; private readonly TimeSpan _stabilityTimeout; @@ -253,13 +255,13 @@ private sealed class StabilityReached private ICancelable _stabilityTask; private ILoggingAdapter _log; - public SplitBrainDecider(TimeSpan stableAfter, ISplitBrainStrategy strategy) + public SplitBrainDecider(TimeSpan stableAfter, ISplitBrainStrategy strategy, Cluster cluster) { if (strategy == null) throw new ArgumentNullException(nameof(strategy)); _stabilityTimeout = stableAfter; _strategy = strategy; - _cluster = Cluster.Get(Context.System); + _cluster = cluster; } public ILoggingAdapter Log => _log ?? (_log = Context.GetLogger());