From a5c5b653bbb27adac166a2f37b26a0c25ec2f6ae Mon Sep 17 00:00:00 2001 From: Bartosz Sypytkowski Date: Thu, 21 Dec 2017 22:04:03 +0100 Subject: [PATCH 1/3] Member status: Weakly up (#3099) * cluster member status (weakly-up): initial commit * regenerated protobuf cluster messages * cluster approvals API for weakly up status * fixed WeaklyUp specs * turned off weakly-up in necessary specs * turned weakly-up = off by default --- .../DistributedPubSubMediator.cs | 4 + .../Akka.DistributedData/Replicator.cs | 9 + .../CoreAPISpec.ApproveCluster.approved.txt | 6 + .../ConvergenceSpec.cs | 4 +- .../MemberWeaklyUpSpec.cs | 161 +++++++++++++++ .../MinMembersBeforeUpSpec.cs | 51 +++++ .../RestartNode3Spec.cs | 4 +- src/core/Akka.Cluster/ClusterDaemon.cs | 41 +++- src/core/Akka.Cluster/ClusterEvent.cs | 38 +++- src/core/Akka.Cluster/ClusterRemoteWatcher.cs | 41 ++-- src/core/Akka.Cluster/ClusterSettings.cs | 11 ++ .../Akka.Cluster/Configuration/Cluster.conf | 8 + src/core/Akka.Cluster/Member.cs | 24 ++- .../Routing/ClusterRoutingConfig.cs | 3 +- .../Serialization/ClusterMessageSerializer.cs | 131 ++++--------- .../Serialization/Proto/ClusterMessages.g.cs | 35 ++-- src/core/Akka.Remote.TestKit/CommandLine.cs | 11 +- src/core/Akka.Remote.TestKit/Controller.cs | 184 ++++++++---------- src/core/Akka.Remote.TestKit/DataTypes.cs | 45 ++--- src/protobuf/ClusterMessages.proto | 1 + 20 files changed, 528 insertions(+), 284 deletions(-) create mode 100644 src/core/Akka.Cluster.Tests.MultiNode/MemberWeaklyUpSpec.cs diff --git a/src/contrib/cluster/Akka.Cluster.Tools/PublishSubscribe/DistributedPubSubMediator.cs b/src/contrib/cluster/Akka.Cluster.Tools/PublishSubscribe/DistributedPubSubMediator.cs index e19b0ef7f71..949d73f0d3b 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/PublishSubscribe/DistributedPubSubMediator.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/PublishSubscribe/DistributedPubSubMediator.cs @@ -345,6 +345,10 @@ public DistributedPubSubMediator(DistributedPubSubSettings settings) { if (IsMatchingRole(up.Member)) _nodes.Add(up.Member.Address); }); + Receive(weaklyUp => + { + if (IsMatchingRole(weaklyUp.Member)) _nodes.Add(weaklyUp.Member.Address); + }); Receive(left => { if (IsMatchingRole(left.Member)) diff --git a/src/contrib/cluster/Akka.DistributedData/Replicator.cs b/src/contrib/cluster/Akka.DistributedData/Replicator.cs index 9905f8fb5e5..adb7d394500 100644 --- a/src/contrib/cluster/Akka.DistributedData/Replicator.cs +++ b/src/contrib/cluster/Akka.DistributedData/Replicator.cs @@ -494,6 +494,7 @@ private void NormalReceive() Receive(s => ReceiveSubscribe(s.Key, s.Subscriber)); Receive(u => ReceiveUnsubscribe(u.Key, u.Subscriber)); Receive(t => ReceiveTerminated(t.ActorRef)); + Receive(m => ReceiveMemberWeaklyUp(m.Member)); Receive(m => ReceiveMemberUp(m.Member)); Receive(m => ReceiveMemberRemoved(m.Member)); Receive(_ => { }); @@ -1193,6 +1194,14 @@ private void ReceiveTerminated(IActorRef terminated) } } + private void ReceiveMemberWeaklyUp(Member m) + { + if (MatchingRole(m) && m.Address != _selfAddress) + { + _weaklyUpNodes = _weaklyUpNodes.Add(m.Address); + } + } + private void ReceiveMemberUp(Member m) { if (MatchingRole(m) && m.Address != _selfAddress) diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.approved.txt index 5a554f77937..4f63c8ed2ed 100644 --- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.approved.txt +++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCluster.approved.txt @@ -114,6 +114,10 @@ namespace Akka.Cluster { public MemberUp(Akka.Cluster.Member member) { } } + public sealed class MemberWeaklyUp : Akka.Cluster.ClusterEvent.MemberStatusChange + { + public MemberWeaklyUp(Akka.Cluster.Member member) { } + } public abstract class ReachabilityEvent : Akka.Cluster.ClusterEvent.IClusterDomainEvent, Akka.Cluster.ClusterEvent.IReachabilityEvent { protected ReachabilityEvent(Akka.Cluster.Member member) { } @@ -159,6 +163,7 @@ namespace Akka.Cluster public sealed class ClusterSettings { public ClusterSettings(Akka.Configuration.Config config, string systemName) { } + public bool AllowWeaklyUpMembers { get; } public System.Nullable AutoDownUnreachableAfter { get; } public System.Type DowningProviderType { get; } [System.ObsoleteAttribute("Use Cluster.DowningProvider.DownRemovalMargin [1.1.2]")] @@ -224,6 +229,7 @@ namespace Akka.Cluster Exiting = 3, Down = 4, Removed = 5, + WeaklyUp = 6, } public sealed class NoDowning : Akka.Cluster.IDowningProvider { diff --git a/src/core/Akka.Cluster.Tests.MultiNode/ConvergenceSpec.cs b/src/core/Akka.Cluster.Tests.MultiNode/ConvergenceSpec.cs index e7846e71bbd..eaf3edbf2b7 100644 --- a/src/core/Akka.Cluster.Tests.MultiNode/ConvergenceSpec.cs +++ b/src/core/Akka.Cluster.Tests.MultiNode/ConvergenceSpec.cs @@ -38,7 +38,9 @@ public ConvergenceSpecConfig(bool failureDetectorPuppet) CommonConfig = ConfigurationFactory.ParseString(@"akka.cluster.publish-stats-interval = 25s") .WithFallback(MultiNodeLoggingConfig.LoggingConfig) .WithFallback(DebugConfig(true)) - .WithFallback(@"akka.cluster.failure-detector.threshold = 4") + .WithFallback(@" + akka.cluster.failure-detector.threshold = 4 + akka.cluster.allow-weakly-up-members = off") .WithFallback(MultiNodeClusterSpec.ClusterConfig(failureDetectorPuppet)); } } diff --git a/src/core/Akka.Cluster.Tests.MultiNode/MemberWeaklyUpSpec.cs b/src/core/Akka.Cluster.Tests.MultiNode/MemberWeaklyUpSpec.cs new file mode 100644 index 00000000000..853098bea87 --- /dev/null +++ b/src/core/Akka.Cluster.Tests.MultiNode/MemberWeaklyUpSpec.cs @@ -0,0 +1,161 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) 2009-2016 Lightbend Inc. +// Copyright (C) 2013-2016 Akka.NET project +// +//----------------------------------------------------------------------- + +using System; +using System.Collections.Immutable; +using System.Linq; +using Akka.Cluster.TestKit; +using Akka.Configuration; +using Akka.Remote.TestKit; +using Akka.Remote.Transport; +using Akka.TestKit; + +namespace Akka.Cluster.Tests.MultiNode +{ + public class MemberWeaklyUpConfig : MultiNodeConfig + { + public RoleName First { get; } + public RoleName Second { get; } + public RoleName Third { get; } + public RoleName Fourth { get; } + public RoleName Fifth { get; } + + public MemberWeaklyUpConfig() + { + First = Role("first"); + Second = Role("second"); + Third = Role("third"); + Fourth = Role("fourth"); + Fifth = Role("fifth"); + + CommonConfig = DebugConfig(on: false) + .WithFallback(ConfigurationFactory.ParseString(@" + akka.remote.retry-gate-closed-for = 3s + akka.cluster.allow-weakly-up-members = on")) + .WithFallback(MultiNodeClusterSpec.ClusterConfig()); + + TestTransport = true; + } + } + + public class MemberWeaklyUpSpec : MultiNodeClusterSpec + { + private readonly MemberWeaklyUpConfig _config; + private readonly ImmutableArray _side1; + private readonly ImmutableArray _side2; + + public MemberWeaklyUpSpec() : this(new MemberWeaklyUpConfig()) + { + } + + private MemberWeaklyUpSpec(MemberWeaklyUpConfig config) : base(config, typeof(MemberWeaklyUpSpec)) + { + _config = config; + _side1 = ImmutableArray.CreateRange(new[] { config.First, config.Second }); + _side2 = ImmutableArray.CreateRange(new[] { config.Third, config.Fourth, config.Fifth }); + MuteMarkingAsUnreachable(); + } + + [MultiNodeFact] + public void Spec() + { + A_cluster_of_3_members_should_reach_initial_convergence(); + A_cluster_of_3_members_should_detect_network_partition_and_mark_nodes_on_the_other_side_as_unreachable(); + A_cluster_of_3_members_should_accept_joining_on_each_side_and_set_status_to_WeaklyUp(); + A_cluster_of_3_members_should_change_status_to_Up_after_healed_network_partition(); + } + + public void A_cluster_of_3_members_should_reach_initial_convergence() + { + AwaitClusterUp(_config.First, _config.Third, _config.Fourth); + EnterBarrier("after-1"); + } + + public void A_cluster_of_3_members_should_detect_network_partition_and_mark_nodes_on_the_other_side_as_unreachable() + { + Within(TimeSpan.FromSeconds(20), () => + { + RunOn(() => + { + // split the cluster in two parts (first, second) / (third, fourth, fifth) + foreach (var role1 in _side1) + foreach (var role2 in _side2) + TestConductor.Blackhole(role1, role2, ThrottleTransportAdapter.Direction.Both).Wait(TimeSpan.FromSeconds(3)); + }, _config.First); + + EnterBarrier("after-split"); + + RunOn(() => + { + AwaitAssert(() => + ClusterView.UnreachableMembers + .Select(m => m.Address).ToImmutableHashSet() + .ShouldBe(ImmutableHashSet.CreateRange(new[] { GetAddress(_config.Third), GetAddress(_config.Fourth) }))); + }, _config.First); + + RunOn(() => + { + AwaitAssert(() => + ClusterView.UnreachableMembers + .Select(m => m.Address).ToImmutableHashSet() + .ShouldBe(ImmutableHashSet.CreateRange(new[] { GetAddress(_config.First) }))); + }, _config.Third, _config.Fourth); + + EnterBarrier("after-2"); + }); + } + + public void A_cluster_of_3_members_should_accept_joining_on_each_side_and_set_status_to_WeaklyUp() + { + Within(TimeSpan.FromSeconds(20), () => + { + RunOn(() => Cluster.Get(Sys).Join(GetAddress(_config.First)), _config.Second); + RunOn(() => Cluster.Get(Sys).Join(GetAddress(_config.Fourth)), _config.Fifth); + + EnterBarrier("joined"); + + RunOn(() => AwaitAssert(() => + { + ClusterView.Members.Count.ShouldBe(4); + ClusterView.Members.Any(m => m.Address == GetAddress(_config.Second) && m.Status == MemberStatus.WeaklyUp).ShouldBe(true); + + }), _side1.ToArray()); + + RunOn(() => AwaitAssert(() => + { + ClusterView.Members.Count.ShouldBe(4); + ClusterView.Members.Any(m => m.Address == GetAddress(_config.Fifth) && m.Status == MemberStatus.WeaklyUp).ShouldBe(true); + + }), _side2.ToArray()); + + EnterBarrier("after-3"); + }); + } + + public void A_cluster_of_3_members_should_change_status_to_Up_after_healed_network_partition() + { + Within(TimeSpan.FromSeconds(20), () => + { + RunOn(() => + { + foreach (var role1 in _side1) + foreach (var role2 in _side2) + { + TestConductor.PassThrough(role1, role2, ThrottleTransportAdapter.Direction.Both).Wait(TimeSpan.FromSeconds(3)); + } + }, _config.First); + + EnterBarrier("after-passThrough"); + + AwaitAllReachable(); + AwaitMembersUp(5); + + EnterBarrier("after-4"); + }); + } + } +} \ No newline at end of file diff --git a/src/core/Akka.Cluster.Tests.MultiNode/MinMembersBeforeUpSpec.cs b/src/core/Akka.Cluster.Tests.MultiNode/MinMembersBeforeUpSpec.cs index 7c147e174a9..57ac41e381f 100644 --- a/src/core/Akka.Cluster.Tests.MultiNode/MinMembersBeforeUpSpec.cs +++ b/src/core/Akka.Cluster.Tests.MultiNode/MinMembersBeforeUpSpec.cs @@ -17,6 +17,8 @@ namespace Akka.Cluster.Tests.MultiNode { + #region Member.Up + public class MinMembersBeforeUpSpecConfig : MultiNodeConfig { public readonly RoleName First; @@ -83,6 +85,55 @@ public void Cluster_leader_must_wait_with_moving_members_to_up_until_minimum_num } } + #endregion + + #region Member.WeaklyUp + + public class MinMembersBeforeUpWithWeaklyUpSpecConfig : MultiNodeConfig + { + public readonly RoleName First; + public readonly RoleName Second; + public readonly RoleName Third; + + public MinMembersBeforeUpWithWeaklyUpSpecConfig() + { + First = Role("first"); + Second = Role("second"); + Third = Role("third"); + + CommonConfig = ConfigurationFactory.ParseString(@" + akka.cluster.min-nr-of-members = 3 + akka.cluster.allow-weakly-up-members = on + ").WithFallback(MultiNodeClusterSpec.ClusterConfigWithFailureDetectorPuppet()); + } + } + public class MinMembersBeforeUpWithWeaklyUpNode1 : MinMembersBeforeUpWithWeaklyUpSpec { } + public class MinMembersBeforeUpWithWeaklyUpNode2 : MinMembersBeforeUpWithWeaklyUpSpec { } + public class MinMembersBeforeUpWithWeaklyUpNode3 : MinMembersBeforeUpWithWeaklyUpSpec { } + + public abstract class MinMembersBeforeUpWithWeaklyUpSpec : MinMembersBeforeUpBase + { + protected MinMembersBeforeUpWithWeaklyUpSpec() : this(new MinMembersBeforeUpWithWeaklyUpSpecConfig()) + { + } + + protected MinMembersBeforeUpWithWeaklyUpSpec(MinMembersBeforeUpWithWeaklyUpSpecConfig config) + : base(config, typeof(MinMembersBeforeUpWithWeaklyUpSpec)) + { + First = config.First; + Second = config.Second; + Third = config.Third; + } + + [MultiNodeFact] + public void Cluster_leader_must_wait_with_moving_members_to_up_until_minimum_number_of_members_have_joined_with_WeaklyUp_enabled() + { + TestWaitMovingMembersToUp(); + } + } + + #endregion + public class MinMembersOfRoleBeforeUpSpec : MinMembersBeforeUpBase { public MinMembersOfRoleBeforeUpSpec() : this(new MinMembersOfRoleBeforeUpSpecConfig()) diff --git a/src/core/Akka.Cluster.Tests.MultiNode/RestartNode3Spec.cs b/src/core/Akka.Cluster.Tests.MultiNode/RestartNode3Spec.cs index 1b3f0cc6fa0..2e727300a25 100644 --- a/src/core/Akka.Cluster.Tests.MultiNode/RestartNode3Spec.cs +++ b/src/core/Akka.Cluster.Tests.MultiNode/RestartNode3Spec.cs @@ -31,7 +31,9 @@ public RestartNode3SpecConfig() Third = Role("third"); CommonConfig = DebugConfig(false) - .WithFallback(ConfigurationFactory.ParseString("akka.cluster.auto-down-unreachable-after = off")) + .WithFallback(ConfigurationFactory.ParseString(@" + akka.cluster.auto-down-unreachable-after = off + akka.cluster.allow-weakly-up-members = off")) .WithFallback(MultiNodeClusterSpec.ClusterConfig()); TestTransport = true; diff --git a/src/core/Akka.Cluster/ClusterDaemon.cs b/src/core/Akka.Cluster/ClusterDaemon.cs index 6eef0a05a67..a80cdfaa606 100644 --- a/src/core/Akka.Cluster/ClusterDaemon.cs +++ b/src/core/Akka.Cluster/ClusterDaemon.cs @@ -2120,6 +2120,10 @@ public void LeaderActions() else { _leaderActionCounter += 1; + + if (_cluster.Settings.AllowWeaklyUpMembers && _leaderActionCounter >= 3) + MoveJoiningToWeaklyUp(); + if (_leaderActionCounter == firstNotice || _leaderActionCounter % periodicNotice == 0) { _log.Info( @@ -2138,6 +2142,39 @@ public void LeaderActions() ShutdownSelfWhenDown(); } + private void MoveJoiningToWeaklyUp() + { + var localGossip = _latestGossip; + var localMembers = localGossip.Members; + var enoughMembers = IsMinNrOfMembersFulfilled(); + + bool IsJoiningToWeaklyUp(Member m) => m.Status == MemberStatus.Joining + && enoughMembers + && _latestGossip.ReachabilityExcludingDownedObservers.Value.IsReachable(m.UniqueAddress); + + var changedMembers = localMembers + .Where(IsJoiningToWeaklyUp) + .Select(m => m.Copy(MemberStatus.WeaklyUp)) + .ToImmutableSortedSet(); + + if (!changedMembers.IsEmpty) + { + // replace changed members + var newMembers = changedMembers.Union(localMembers); + var newGossip = localGossip.Copy(members: newMembers); + UpdateLatestGossip(newGossip); + + // log status change + foreach (var m in changedMembers) + { + _log.Info("Leader is moving node [{0}] to [{1}]", m.Address, m.Status); + } + + Publish(newGossip); + if (_cluster.Settings.PublishStatsInterval == TimeSpan.Zero) PublishInternalStats(); + } + } + private void ShutdownSelfWhenDown() { if (_latestGossip.GetMember(SelfUniqueAddress).Status == MemberStatus.Down) @@ -2197,7 +2234,7 @@ public void LeaderActionsOnConvergence() var localSeen = localOverview.Seen; bool enoughMembers = IsMinNrOfMembersFulfilled(); - Func isJoiningUp = m => m.Status == MemberStatus.Joining && enoughMembers; + bool IsJoiningUp(Member m) => (m.Status == MemberStatus.Joining || m.Status == MemberStatus.WeaklyUp) && enoughMembers; var removedUnreachable = localOverview.Reachability.AllUnreachableOrTerminated.Select(localGossip.GetMember) @@ -2211,7 +2248,7 @@ public void LeaderActionsOnConvergence() var upNumber = 0; var changedMembers = localMembers.Select(m => { - if (isJoiningUp(m)) + if (IsJoiningUp(m)) { // Move JOINING => UP (once all nodes have seen that this node is JOINING, i.e. we have a convergence) // and minimum number of nodes have joined the cluster diff --git a/src/core/Akka.Cluster/ClusterEvent.cs b/src/core/Akka.Cluster/ClusterEvent.cs index d31169c5d89..b49261eeec3 100644 --- a/src/core/Akka.Cluster/ClusterEvent.cs +++ b/src/core/Akka.Cluster/ClusterEvent.cs @@ -294,6 +294,22 @@ public MemberUp(Member member) : base(member, MemberStatus.Up) { } } + /// + /// Member status changed to WeaklyUp. + /// A joining member can be moved to if convergence + /// cannot be reached, i.e. there are unreachable nodes. + /// It will be moved to when convergence is reached. + /// + public sealed class MemberWeaklyUp : MemberStatusChange + { + /// + /// Initializes a new instance of the class. + /// + /// The node that changed state. + public MemberWeaklyUp(Member member) + : base(member, MemberStatus.WeaklyUp) { } + } + /// /// This class represents a event where the /// cluster node changed its status to . @@ -852,10 +868,24 @@ private static IEnumerable CollectMemberEvents(IEnumerable { foreach (var member in members) { - if (member.Status == MemberStatus.Joining) yield return new MemberJoined(member); - if (member.Status == MemberStatus.Up) yield return new MemberUp(member); - if (member.Status == MemberStatus.Leaving) yield return new MemberLeft(member); - if (member.Status == MemberStatus.Exiting) yield return new MemberExited(member); + switch (member.Status) + { + case MemberStatus.Joining: + yield return new MemberJoined(member); + break; + case MemberStatus.WeaklyUp: + yield return new MemberWeaklyUp(member); + break; + case MemberStatus.Up: + yield return new MemberUp(member); + break; + case MemberStatus.Leaving: + yield return new MemberLeft(member); + break; + case MemberStatus.Exiting: + yield return new MemberExited(member); + break; + } } } diff --git a/src/core/Akka.Cluster/ClusterRemoteWatcher.cs b/src/core/Akka.Cluster/ClusterRemoteWatcher.cs index e60d1e16b1f..6fff6dc2da6 100644 --- a/src/core/Akka.Cluster/ClusterRemoteWatcher.cs +++ b/src/core/Akka.Cluster/ClusterRemoteWatcher.cs @@ -89,32 +89,27 @@ protected override void PostStop() /// TBD protected override void OnReceive(object message) { - var state = message as ClusterEvent.CurrentClusterState; - if (state != null) + switch (message) { - _clusterNodes = - state.Members.Select(m => m.Address).Where(a => a != _cluster.SelfAddress).ToImmutableHashSet(); - foreach (var node in _clusterNodes) TakeOverResponsibility(node); - Unreachable.ExceptWith(_clusterNodes); - return; + case ClusterEvent.CurrentClusterState state: + _clusterNodes = + state.Members.Select(m => m.Address).Where(a => a != _cluster.SelfAddress).ToImmutableHashSet(); + foreach (var node in _clusterNodes) TakeOverResponsibility(node); + Unreachable.ExceptWith(_clusterNodes); + return; + case ClusterEvent.MemberUp up: + MemberUp(up.Member); + return; + case ClusterEvent.MemberWeaklyUp weaklyUp: + MemberUp(weaklyUp.Member); + return; + case ClusterEvent.MemberRemoved removed: + MemberRemoved(removed.Member, removed.PreviousStatus); + return; + case ClusterEvent.IMemberEvent _: + return; // not interesting } - var memberUp = message as ClusterEvent.MemberUp; - if (memberUp != null) - { - MemberUp(memberUp.Member); - return; - } - - var memberRemoved = message as ClusterEvent.MemberRemoved; - if (memberRemoved != null) - { - MemberRemoved(memberRemoved.Member, memberRemoved.PreviousStatus); - return; - } - - if (message is ClusterEvent.IMemberEvent) return; // not interesting - base.OnReceive(message); } diff --git a/src/core/Akka.Cluster/ClusterSettings.cs b/src/core/Akka.Cluster/ClusterSettings.cs index 7c42e54f30d..2e1c79e7408 100644 --- a/src/core/Akka.Cluster/ClusterSettings.cs +++ b/src/core/Akka.Cluster/ClusterSettings.cs @@ -81,6 +81,7 @@ public ClusterSettings(Config config, string systemName) DowningProviderType = typeof(NoDowning); RunCoordinatedShutdownWhenDown = cc.GetBoolean("run-coordinated-shutdown-when-down"); + AllowWeaklyUpMembers = cc.GetBoolean("allow-weakly-up-members"); } /// @@ -229,6 +230,16 @@ public ClusterSettings(Config config, string systemName) /// means, such as being downed. /// public bool RunCoordinatedShutdownWhenDown { get; } + + /// + /// If this is set to "off", the leader will not move members to during a network + /// split. This feature allows the leader to accept members to be + /// so they become part of the cluster even during a network split. The leader will + /// move members to after 3 rounds of 'leader-actions-interval' + /// without convergence. + /// The leader will move members to status once convergence has been reached. + /// + public bool AllowWeaklyUpMembers { get; } } } diff --git a/src/core/Akka.Cluster/Configuration/Cluster.conf b/src/core/Akka.Cluster/Configuration/Cluster.conf index 677b7229b37..6673b0965ee 100644 --- a/src/core/Akka.Cluster/Configuration/Cluster.conf +++ b/src/core/Akka.Cluster/Configuration/Cluster.conf @@ -50,6 +50,14 @@ akka { # `akka.cluster.DowningProvider` having a public one argument constructor accepting an `ActorSystem` downing-provider-class = "" + # If this is set to "off", the leader will not move 'Joining' members to 'Up' during a network + # split. This feature allows the leader to accept 'Joining' members to be 'WeaklyUp' + # so they become part of the cluster even during a network split. The leader will + # move `Joining` members to 'WeaklyUp' after 3 rounds of 'leader-actions-interval' + # without convergence. + # The leader will move 'WeaklyUp' members to 'Up' status once convergence has been reached. + allow-weakly-up-members = off + # The roles of this member. List of strings, e.g. roles = ["A", "B"]. # The roles are part of the membership information and can be used by # routers or other services to distribute work to certain member types, diff --git a/src/core/Akka.Cluster/Member.cs b/src/core/Akka.Cluster/Member.cs index 31b555fba83..550a4f39b35 100644 --- a/src/core/Akka.Cluster/Member.cs +++ b/src/core/Akka.Cluster/Member.cs @@ -248,6 +248,8 @@ public int Compare(Member a, Member b) if (@bs == MemberStatus.Exiting) return -1; if (@as == MemberStatus.Joining) return 1; if (@bs == MemberStatus.Joining) return -1; + if (@as == MemberStatus.WeaklyUp) return 1; + if (@bs == MemberStatus.WeaklyUp) return -1; return Ordering.Compare(a, b); } } @@ -373,6 +375,8 @@ public static Member HighestPriorityOf(Member m1, Member m2) if (m2Status == MemberStatus.Leaving) return m2; if (m1Status == MemberStatus.Joining) return m2; if (m2Status == MemberStatus.Joining) return m1; + if (m1Status == MemberStatus.WeaklyUp) return m2; + if (m2Status == MemberStatus.WeaklyUp) return m1; return m1; } @@ -382,7 +386,8 @@ public static Member HighestPriorityOf(Member m1, Member m2) internal static readonly ImmutableDictionary> AllowedTransitions = new Dictionary> { - {MemberStatus.Joining, ImmutableHashSet.Create(MemberStatus.Up, MemberStatus.Down, MemberStatus.Removed)}, + {MemberStatus.Joining, ImmutableHashSet.Create(MemberStatus.WeaklyUp, MemberStatus.Up, MemberStatus.Down, MemberStatus.Removed)}, + {MemberStatus.WeaklyUp, ImmutableHashSet.Create(MemberStatus.Up, MemberStatus.Down, MemberStatus.Removed) }, {MemberStatus.Up, ImmutableHashSet.Create(MemberStatus.Leaving, MemberStatus.Down, MemberStatus.Removed)}, {MemberStatus.Leaving, ImmutableHashSet.Create(MemberStatus.Exiting, MemberStatus.Down, MemberStatus.Removed)}, {MemberStatus.Down, ImmutableHashSet.Create(MemberStatus.Removed)}, @@ -402,27 +407,32 @@ public enum MemberStatus /// /// Indicates that a new node is joining the cluster. /// - Joining, + Joining = 0, /// /// Indicates that a node is a current member of the cluster. /// - Up, + Up = 1, /// /// Indicates that a node is beginning to leave the cluster. /// - Leaving, + Leaving = 2, /// /// Indicates that all nodes are aware that this node is leaving the cluster. /// - Exiting, + Exiting = 3, /// /// Node was forcefully removed from the cluster by means of /// - Down, + Down = 4, /// /// Node was removed as a member from the cluster. /// - Removed + Removed = 5, + /// + /// Indicates that new node has already joined, but it cannot be set to + /// because cluster convergence cannot be reached i.e. because of unreachable nodes. + /// + WeaklyUp = 6, } /// diff --git a/src/core/Akka.Cluster/Routing/ClusterRoutingConfig.cs b/src/core/Akka.Cluster/Routing/ClusterRoutingConfig.cs index 2e11a0c1707..34bcfc5042b 100644 --- a/src/core/Akka.Cluster/Routing/ClusterRoutingConfig.cs +++ b/src/core/Akka.Cluster/Routing/ClusterRoutingConfig.cs @@ -708,7 +708,8 @@ protected override void PostStop() /// TBD public bool IsAvailable(Member member) { - return member.Status == MemberStatus.Up && SatisfiesRole(member.Roles) && + return (member.Status == MemberStatus.Up || member.Status == MemberStatus.WeaklyUp) && + SatisfiesRole(member.Roles) && (Settings.AllowLocalRoutees || member.Address != Cluster.SelfAddress); } diff --git a/src/core/Akka.Cluster/Serialization/ClusterMessageSerializer.cs b/src/core/Akka.Cluster/Serialization/ClusterMessageSerializer.cs index 949313282ab..958cbc383de 100644 --- a/src/core/Akka.Cluster/Serialization/ClusterMessageSerializer.cs +++ b/src/core/Akka.Cluster/Serialization/ClusterMessageSerializer.cs @@ -49,84 +49,37 @@ public ClusterMessageSerializer(ExtendedActorSystem system) : base(system) public override byte[] ToBinary(object obj) { - var heartbeat = obj as ClusterHeartbeatSender.Heartbeat; - if (heartbeat != null) + switch (obj) { - return AddressToProto(heartbeat.From).ToByteArray(); + case ClusterHeartbeatSender.Heartbeat heartbeat: + return AddressToProto(heartbeat.From).ToByteArray(); + case ClusterHeartbeatSender.HeartbeatRsp heartbeatRsp: + return UniqueAddressToProto(heartbeatRsp.From).ToByteArray(); + case GossipEnvelope gossipEnvelope: + return GossipEnvelopeToProto(gossipEnvelope); + case GossipStatus gossipStatus: + return GossipStatusToProto(gossipStatus); + case InternalClusterAction.Join @join: + return JoinToByteArray(@join); + case InternalClusterAction.Welcome welcome: + return WelcomeMessageBuilder(welcome); + case ClusterUserAction.Leave leave: + return AddressToProto(leave.Address).ToByteArray(); + case ClusterUserAction.Down down: + return AddressToProto(down.Address).ToByteArray(); + case InternalClusterAction.InitJoin _: + return new Google.Protobuf.WellKnownTypes.Empty().ToByteArray(); + case InternalClusterAction.InitJoinAck initJoinAck: + return AddressToProto(initJoinAck.Address).ToByteArray(); + case InternalClusterAction.InitJoinNack initJoinNack: + return AddressToProto(initJoinNack.Address).ToByteArray(); + case InternalClusterAction.ExitingConfirmed exitingConfirmed: + return UniqueAddressToProto(exitingConfirmed.Address).ToByteArray(); + case ClusterRouterPool pool: + return ClusterRouterPoolToByteArray(pool); + default: + throw new ArgumentException($"Can't serialize object of type [{obj.GetType()}] in [{nameof(ClusterMessageSerializer)}]"); } - - var heartbeatRsp = obj as ClusterHeartbeatSender.HeartbeatRsp; - if (heartbeatRsp != null) - { - return UniqueAddressToProto(heartbeatRsp.From).ToByteArray(); - } - - var gossipEnvelope = obj as GossipEnvelope; - if (gossipEnvelope != null) - { - return GossipEnvelopeToProto(gossipEnvelope); - } - - var gossipStatus = obj as GossipStatus; - if (gossipStatus != null) - { - return GossipStatusToProto(gossipStatus); - } - - var join = obj as InternalClusterAction.Join; - if (join != null) - { - return JoinToByteArray(join); - } - - var welcome = obj as InternalClusterAction.Welcome; - if (welcome != null) - { - return WelcomeMessageBuilder(welcome); - } - - var leave = obj as ClusterUserAction.Leave; - if (leave != null) - { - return AddressToProto(leave.Address).ToByteArray(); - } - - var down = obj as ClusterUserAction.Down; - if (down != null) - { - return AddressToProto(down.Address).ToByteArray(); - } - - if (obj is InternalClusterAction.InitJoin) - { - return new Google.Protobuf.WellKnownTypes.Empty().ToByteArray(); - } - - var initJoinAck = obj as InternalClusterAction.InitJoinAck; - if (initJoinAck != null) - { - return AddressToProto(initJoinAck.Address).ToByteArray(); - } - - var initJoinNack = obj as InternalClusterAction.InitJoinNack; - if (initJoinNack != null) - { - return AddressToProto(initJoinNack.Address).ToByteArray(); - } - - var exitingConfirmed = obj as InternalClusterAction.ExitingConfirmed; - if (exitingConfirmed != null) - { - return UniqueAddressToProto(exitingConfirmed.Address).ToByteArray(); - } - - var pool = obj as ClusterRouterPool; - if (pool != null) - { - return ClusterRouterPoolToByteArray(pool); - } - - throw new ArgumentException($"Can't serialize object of type [{obj.GetType()}] in [{nameof(ClusterMessageSerializer)}]"); } public override object FromBinary(byte[] bytes, Type type) @@ -276,21 +229,21 @@ private static Proto.Msg.Gossip GossipToProto(Gossip gossip) var allHashes = gossip.Version.Versions.Keys.Select(x => x.ToString()).ToList(); var hashMapping = allHashes.ZipWithIndex(); - Func mapUniqueAddress = address => MapWithErrorMessage(addressMapping, address, "address"); + int MapUniqueAddress(UniqueAddress address) => MapWithErrorMessage(addressMapping, address, "address"); - Func memberToProto = m => + Proto.Msg.Member MemberToProto(Member m) { var protoMember = new Proto.Msg.Member(); - protoMember.AddressIndex = mapUniqueAddress(m.UniqueAddress); + protoMember.AddressIndex = MapUniqueAddress(m.UniqueAddress); protoMember.UpNumber = m.UpNumber; protoMember.Status = (Proto.Msg.Member.Types.MemberStatus)m.Status; protoMember.RolesIndexes.AddRange(m.Roles.Select(s => MapWithErrorMessage(roleMapping, s, "role"))); return protoMember; - }; + } var reachabilityProto = ReachabilityToProto(gossip.Overview.Reachability, addressMapping); - var membersProtos = gossip.Members.Select(memberToProto); - var seenProtos = gossip.Overview.Seen.Select(mapUniqueAddress); + var membersProtos = gossip.Members.Select((Func)MemberToProto); + var seenProtos = gossip.Overview.Seen.Select((Func)MapUniqueAddress); var overview = new Proto.Msg.GossipOverview(); overview.Seen.AddRange(seenProtos); @@ -312,16 +265,14 @@ private static Gossip GossipFrom(Proto.Msg.Gossip gossip) var roleMapping = gossip.AllRoles.ToList(); var hashMapping = gossip.AllHashes.ToList(); - Func memberFromProto = member => - { - return Member.Create( - addressMapping[member.AddressIndex], - member.UpNumber, - (MemberStatus) member.Status, + Member MemberFromProto(Proto.Msg.Member member) => + Member.Create( + addressMapping[member.AddressIndex], + member.UpNumber, + (MemberStatus)member.Status, member.RolesIndexes.Select(x => roleMapping[x]).ToImmutableHashSet()); - }; - var members = gossip.Members.Select(memberFromProto).ToImmutableSortedSet(Member.Ordering); + var members = gossip.Members.Select((Func)MemberFromProto).ToImmutableSortedSet(Member.Ordering); var reachability = ReachabilityFromProto(gossip.Overview.ObserverReachability, addressMapping); var seen = gossip.Overview.Seen.Select(x => addressMapping[x]).ToImmutableHashSet(); var overview = new GossipOverview(seen, reachability); diff --git a/src/core/Akka.Cluster/Serialization/Proto/ClusterMessages.g.cs b/src/core/Akka.Cluster/Serialization/Proto/ClusterMessages.g.cs index 6d82deb4bf1..693fc96e951 100644 --- a/src/core/Akka.Cluster/Serialization/Proto/ClusterMessages.g.cs +++ b/src/core/Akka.Cluster/Serialization/Proto/ClusterMessages.g.cs @@ -55,26 +55,26 @@ static ClusterMessagesReflection() { "YXRpb24uUHJvdG8uTXNnLlN1YmplY3RSZWFjaGFiaWxpdHkuUmVhY2hhYmls", "aXR5U3RhdHVzEg8KB3ZlcnNpb24YBCABKAMiRAoSUmVhY2hhYmlsaXR5U3Rh", "dHVzEg0KCVJlYWNoYWJsZRAAEg8KC1VucmVhY2hhYmxlEAESDgoKVGVybWlu", - "YXRlZBACIusBCgZNZW1iZXISFAoMYWRkcmVzc0luZGV4GAEgASgFEhAKCHVw", + "YXRlZBACIvkBCgZNZW1iZXISFAoMYWRkcmVzc0luZGV4GAEgASgFEhAKCHVw", "TnVtYmVyGAIgASgFEkkKBnN0YXR1cxgDIAEoDjI5LkFra2EuQ2x1c3Rlci5T", "ZXJpYWxpemF0aW9uLlByb3RvLk1zZy5NZW1iZXIuTWVtYmVyU3RhdHVzEhgK", - "DHJvbGVzSW5kZXhlcxgEIAMoBUICEAEiVAoMTWVtYmVyU3RhdHVzEgsKB0pv", + "DHJvbGVzSW5kZXhlcxgEIAMoBUICEAEiYgoMTWVtYmVyU3RhdHVzEgsKB0pv", "aW5pbmcQABIGCgJVcBABEgsKB0xlYXZpbmcQAhILCgdFeGl0aW5nEAMSCAoE", - "RG93bhAEEgsKB1JlbW92ZWQQBSKeAQoLVmVjdG9yQ2xvY2sSEQoJdGltZXN0", - "YW1wGAEgASgDEksKCHZlcnNpb25zGAIgAygLMjkuQWtrYS5DbHVzdGVyLlNl", - "cmlhbGl6YXRpb24uUHJvdG8uTXNnLlZlY3RvckNsb2NrLlZlcnNpb24aLwoH", - "VmVyc2lvbhIRCgloYXNoSW5kZXgYASABKAUSEQoJdGltZXN0YW1wGAIgASgD", - "Il8KDVVuaXF1ZUFkZHJlc3MSQQoHYWRkcmVzcxgBIAEoCzIwLkFra2EuUmVt", - "b3RlLlNlcmlhbGl6YXRpb24uUHJvdG8uTXNnLkFkZHJlc3NEYXRhEgsKA3Vp", - "ZBgCIAEoDSKgAQoRQ2x1c3RlclJvdXRlclBvb2wSOAoEcG9vbBgBIAEoCzIq", - "LkFra2EuQ2x1c3Rlci5TZXJpYWxpemF0aW9uLlByb3RvLk1zZy5Qb29sElEK", - "CHNldHRpbmdzGAIgASgLMj8uQWtrYS5DbHVzdGVyLlNlcmlhbGl6YXRpb24u", - "UHJvdG8uTXNnLkNsdXN0ZXJSb3V0ZXJQb29sU2V0dGluZ3MiPAoEUG9vbBIU", - "CgxzZXJpYWxpemVySWQYASABKA0SEAoIbWFuaWZlc3QYAiABKAkSDAoEZGF0", - "YRgDIAEoDCJ8ChlDbHVzdGVyUm91dGVyUG9vbFNldHRpbmdzEhYKDnRvdGFs", - "SW5zdGFuY2VzGAEgASgNEhsKE21heEluc3RhbmNlc1Blck5vZGUYAiABKA0S", - "GQoRYWxsb3dMb2NhbFJvdXRlZXMYAyABKAgSDwoHdXNlUm9sZRgEIAEoCWIG", - "cHJvdG8z")); + "RG93bhAEEgsKB1JlbW92ZWQQBRIMCghXZWFrbHlVcBAGIp4BCgtWZWN0b3JD", + "bG9jaxIRCgl0aW1lc3RhbXAYASABKAMSSwoIdmVyc2lvbnMYAiADKAsyOS5B", + "a2thLkNsdXN0ZXIuU2VyaWFsaXphdGlvbi5Qcm90by5Nc2cuVmVjdG9yQ2xv", + "Y2suVmVyc2lvbhovCgdWZXJzaW9uEhEKCWhhc2hJbmRleBgBIAEoBRIRCgl0", + "aW1lc3RhbXAYAiABKAMiXwoNVW5pcXVlQWRkcmVzcxJBCgdhZGRyZXNzGAEg", + "ASgLMjAuQWtrYS5SZW1vdGUuU2VyaWFsaXphdGlvbi5Qcm90by5Nc2cuQWRk", + "cmVzc0RhdGESCwoDdWlkGAIgASgNIqABChFDbHVzdGVyUm91dGVyUG9vbBI4", + "CgRwb29sGAEgASgLMiouQWtrYS5DbHVzdGVyLlNlcmlhbGl6YXRpb24uUHJv", + "dG8uTXNnLlBvb2wSUQoIc2V0dGluZ3MYAiABKAsyPy5Ba2thLkNsdXN0ZXIu", + "U2VyaWFsaXphdGlvbi5Qcm90by5Nc2cuQ2x1c3RlclJvdXRlclBvb2xTZXR0", + "aW5ncyI8CgRQb29sEhQKDHNlcmlhbGl6ZXJJZBgBIAEoDRIQCghtYW5pZmVz", + "dBgCIAEoCRIMCgRkYXRhGAMgASgMInwKGUNsdXN0ZXJSb3V0ZXJQb29sU2V0", + "dGluZ3MSFgoOdG90YWxJbnN0YW5jZXMYASABKA0SGwoTbWF4SW5zdGFuY2Vz", + "UGVyTm9kZRgCIAEoDRIZChFhbGxvd0xvY2FsUm91dGVlcxgDIAEoCBIPCgd1", + "c2VSb2xlGAQgASgJYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Akka.Remote.Serialization.Proto.Msg.ContainerFormatsReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { @@ -1708,6 +1708,7 @@ internal enum MemberStatus { [pbr::OriginalName("Exiting")] Exiting = 3, [pbr::OriginalName("Down")] Down = 4, [pbr::OriginalName("Removed")] Removed = 5, + [pbr::OriginalName("WeaklyUp")] WeaklyUp = 6, } } diff --git a/src/core/Akka.Remote.TestKit/CommandLine.cs b/src/core/Akka.Remote.TestKit/CommandLine.cs index 026ccb06e4c..24fd7813c11 100644 --- a/src/core/Akka.Remote.TestKit/CommandLine.cs +++ b/src/core/Akka.Remote.TestKit/CommandLine.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Specialized; +using Akka.Configuration; namespace Akka.Remote.TestKit { @@ -33,7 +34,15 @@ public class CommandLine { if (!arg.StartsWith("-D")) continue; var tokens = arg.Substring(2).Split('='); - dictionary.Add(tokens[0], tokens[1]); + + if (tokens.Length == 2) + { + dictionary.Add(tokens[0], tokens[1]); + } + else + { + throw new ConfigurationException($"Command line parameter '{arg}' should follow the pattern [-Dmultinode.=]."); + } } return dictionary; }); diff --git a/src/core/Akka.Remote.TestKit/Controller.cs b/src/core/Akka.Remote.TestKit/Controller.cs index 2cc8eb8e3ae..d259f78062d 100644 --- a/src/core/Akka.Remote.TestKit/Controller.cs +++ b/src/core/Akka.Remote.TestKit/Controller.cs @@ -146,69 +146,52 @@ internal interface IHaveNodeInfo NodeInfo Node { get; } } - internal sealed class NodeInfo + internal sealed class NodeInfo : IEquatable { - readonly RoleName _name; - readonly Address _addr; - readonly IActorRef _fsm; - public NodeInfo(RoleName name, Address addr, IActorRef fsm) { - _name = name; - _addr = addr; - _fsm = fsm; + Name = name; + Addr = addr; + FSM = fsm; } - public RoleName Name - { - get { return _name; } - } + public RoleName Name { get; } - public Address Addr - { - get { return _addr; } - } + public Address Addr { get; } - public IActorRef FSM - { - get { return _fsm; } - } + public IActorRef FSM { get; } - bool Equals(NodeInfo other) + public bool Equals(NodeInfo other) { - return Equals(_name, other._name) && Equals(_addr, other._addr) && Equals(_fsm, other._fsm); + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Equals(Name, other.Name) && Equals(Addr, other.Addr) && Equals(FSM, other.FSM); } /// - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj is NodeInfo && Equals((NodeInfo) obj); - } + public override bool Equals(object obj) => obj is NodeInfo node && Equals(node); /// public override int GetHashCode() { unchecked { - int hashCode = (_name != null ? _name.GetHashCode() : 0); - hashCode = (hashCode*397) ^ (_addr != null ? _addr.GetHashCode() : 0); - hashCode = (hashCode*397) ^ (_fsm != null ? _fsm.GetHashCode() : 0); + int hashCode = (Name != null ? Name.GetHashCode() : 0); + hashCode = (hashCode*397) ^ (Addr != null ? Addr.GetHashCode() : 0); + hashCode = (hashCode*397) ^ (FSM != null ? FSM.GetHashCode() : 0); return hashCode; } } + public override string ToString() => $"NodeInfo({Name}, {Addr})"; + /// /// Compares two specified for equality. /// /// The first used for comparison /// The second used for comparison /// true if both are equal; otherwise false - public static bool operator ==(NodeInfo left, NodeInfo right) - { - return Equals(left, right); - } + public static bool operator ==(NodeInfo left, NodeInfo right) => Equals(left, right); /// /// Compares two specified for inequality. @@ -216,10 +199,7 @@ public override int GetHashCode() /// The first used for comparison /// The second used for comparison /// true if both are not equal; otherwise false - public static bool operator !=(NodeInfo left, NodeInfo right) - { - return !Equals(left, right); - } + public static bool operator !=(NodeInfo left, NodeInfo right) => !Equals(left, right); } public sealed class CreateServerFSM : INoSerializationVerificationNeeded @@ -270,23 +250,23 @@ protected override SupervisorStrategy SupervisorStrategy() { return new OneForOneStrategy(e => { - var barrierTimeout = e as BarrierCoordinator.BarrierTimeoutException; - if (barrierTimeout != null) return FailBarrier(barrierTimeout.BarrierData); - var failedBarrier = e as BarrierCoordinator.FailedBarrierException; - if (failedBarrier != null) return FailBarrier(failedBarrier.BarrierData); - var barrierEmpty = e as BarrierCoordinator.BarrierEmptyException; - if(barrierEmpty != null) return Directive.Resume; - var wrongBarrier = e as BarrierCoordinator.WrongBarrierException; - if (wrongBarrier != null) + switch (e) { - wrongBarrier.Client.Tell(new ToClient(new BarrierResult(wrongBarrier.Barrier, false))); - return FailBarrier(wrongBarrier.BarrierData); + case BarrierCoordinator.BarrierTimeoutException barrierTimeout: + return FailBarrier(barrierTimeout.BarrierData); + case BarrierCoordinator.FailedBarrierException failedBarrier: + return FailBarrier(failedBarrier.BarrierData); + case BarrierCoordinator.BarrierEmptyException barrierEmpty: + return Directive.Resume; + case BarrierCoordinator.WrongBarrierException wrongBarrier: + wrongBarrier.Client.Tell(new ToClient(new BarrierResult(wrongBarrier.Barrier, false))); + return FailBarrier(wrongBarrier.BarrierData); + case BarrierCoordinator.ClientLostException clientLost: + return FailBarrier(clientLost.BarrierData); + case BarrierCoordinator.DuplicateNodeException duplicateNode: + return FailBarrier(duplicateNode.BarrierData); + default: throw new InvalidOperationException($"Cannot process exception of type {e.GetType()}"); } - var clientLost = e as BarrierCoordinator.ClientLostException; - if (clientLost != null) return FailBarrier(clientLost.BarrierData); - var duplicateNode = e as BarrierCoordinator.DuplicateNodeException; - if (duplicateNode != null) return FailBarrier(duplicateNode.BarrierData); - throw new InvalidOperationException($"Cannot process exception of type {e.GetType()}"); }); } @@ -351,63 +331,59 @@ protected override void OnReceive(object message) } if (message is IServerOp) { - if (message is EnterBarrier) - { - _barrier.Forward(message); - return; - } - if (message is FailBarrier) + switch (message) { - _barrier.Forward(message); - return; - } - var getAddress = message as GetAddress; - if (getAddress != null) - { - var node = getAddress.Node; - if (_nodes.TryGetValue(node, out var replyNodeInfo)) - Sender.Tell(new ToClient(new AddressReply(node, replyNodeInfo.Addr))); - else - { - _addrInterest = _addrInterest.SetItem(node, - (_addrInterest.TryGetValue(node, out var existing) - ? existing - : ImmutableHashSet.Create() + case EnterBarrier _: _barrier.Forward(message); return; + case FailBarrier _: _barrier.Forward(message); return; + case GetAddress getAddress: + var node = getAddress.Node; + if (_nodes.TryGetValue(node, out var replyNodeInfo)) + Sender.Tell(new ToClient(new AddressReply(node, replyNodeInfo.Addr))); + else + { + _addrInterest = _addrInterest.SetItem(node, + (_addrInterest.TryGetValue(node, out var existing) + ? existing + : ImmutableHashSet.Create() ).Add(Sender)); - } - return; + } + return; + case Done _: return; //FIXME what should happen? } - if (message is Done) return; //FIXME what should happen? } if (message is ICommandOp) { - var throttle = message as Throttle; - if (throttle != null) - { - var t = _nodes[throttle.Target]; - _nodes[throttle.Node].FSM.Forward(new ToClient(new ThrottleMsg(t.Addr, throttle.Direction, throttle.RateMBit))); - return; - } - var disconnect = message as Disconnect; - if (disconnect != null) - { - var t = _nodes[disconnect.Target]; - _nodes[disconnect.Node].FSM.Forward((new ToClient(new DisconnectMsg(t.Addr, disconnect.Abort)))); - return; - } - var terminate = message as Terminate; - if (terminate != null) + switch (message) { - _barrier.Tell(new BarrierCoordinator.RemoveClient(terminate.Node)); - _nodes[terminate.Node].FSM.Forward(new ToClient(new TerminateMsg(terminate.ShutdownOrExit))); - _nodes = _nodes.Remove(terminate.Node); - return; - } - var remove = message as Remove; - if (remove != null) - { - _barrier.Tell(new BarrierCoordinator.RemoveClient(remove.Node)); - return; + case Throttle throttle: + { + if (!_nodes.TryGetValue(throttle.Target, out var target)) throw new IllegalActorStateException($"Throttle target {throttle.Target} was not found among nodes registered in {nameof(Controller)}: {string.Join(", ", _nodes.Keys)}"); + if (!_nodes.TryGetValue(throttle.Node, out var source)) throw new IllegalActorStateException($"Throttle source {throttle.Node} was not found among nodes registered in {nameof(Controller)}: {string.Join(", ", _nodes.Keys)}"); + + source.FSM.Forward(new ToClient(new ThrottleMsg(target.Addr, throttle.Direction, throttle.RateMBit))); + return; + } + case Disconnect disconnect: + { + if (!_nodes.TryGetValue(disconnect.Target, out var target)) throw new IllegalActorStateException($"Disconnect target {disconnect.Target} was not found among nodes registered in {nameof(Controller)}: {string.Join(", ", _nodes.Keys)}"); + if (!_nodes.TryGetValue(disconnect.Node, out var source)) throw new IllegalActorStateException($"Disconnect source {disconnect.Node} was not found among nodes registered in {nameof(Controller)}: {string.Join(", ", _nodes.Keys)}"); + + source.FSM.Forward((new ToClient(new DisconnectMsg(target.Addr, disconnect.Abort)))); + return; + } + case Terminate terminate: + { + _barrier.Tell(new BarrierCoordinator.RemoveClient(terminate.Node)); + + if (!_nodes.TryGetValue(terminate.Node, out var node)) throw new IllegalActorStateException($"Terminate target {terminate.Node} was not found among nodes registered in {nameof(Controller)}: {string.Join(", ", _nodes.Keys)}"); + + node.FSM.Forward(new ToClient(new TerminateMsg(terminate.ShutdownOrExit))); + _nodes = _nodes.Remove(terminate.Node); + return; + } + case Remove remove: + _barrier.Tell(new BarrierCoordinator.RemoveClient(remove.Node)); + return; } } if (message is GetNodes) diff --git a/src/core/Akka.Remote.TestKit/DataTypes.cs b/src/core/Akka.Remote.TestKit/DataTypes.cs index 009a954fb4b..5b62e0c751c 100644 --- a/src/core/Akka.Remote.TestKit/DataTypes.cs +++ b/src/core/Akka.Remote.TestKit/DataTypes.cs @@ -13,34 +13,25 @@ namespace Akka.Remote.TestKit { - public sealed class RoleName + public sealed class RoleName : IEquatable { - readonly string _name; - public RoleName(string name) { - _name = name; + Name = name; } - bool Equals(RoleName other) + public bool Equals(RoleName other) { - return string.Equals(_name, other._name); + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + return string.Equals(Name, other.Name); } /// - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((RoleName)obj); - } + public override bool Equals(object obj) => obj is RoleName role && Equals(role); /// - public override int GetHashCode() - { - return (_name != null ? _name.GetHashCode() : 0); - } + public override int GetHashCode() => (Name != null ? Name.GetHashCode() : 0); /// /// Compares two specified for equality. @@ -48,10 +39,7 @@ public override int GetHashCode() /// The first used for comparison /// The second used for comparison /// true if both are equal; otherwise false - public static bool operator ==(RoleName left, RoleName right) - { - return Equals(left, right); - } + public static bool operator ==(RoleName left, RoleName right) => Equals(left, right); /// /// Compares two specified for inequality. @@ -59,21 +47,12 @@ public override int GetHashCode() /// The first used for comparison /// The second used for comparison /// true if both are not equal; otherwise false - public static bool operator !=(RoleName left, RoleName right) - { - return !Equals(left, right); - } + public static bool operator !=(RoleName left, RoleName right) => !Equals(left, right); - public string Name - { - get { return _name; } - } + public string Name { get; } /// - public override string ToString() - { - return $"RoleName({_name})"; - } + public override string ToString() => $"RoleName({Name})"; } //TODO: This is messy, better way to do this? diff --git a/src/protobuf/ClusterMessages.proto b/src/protobuf/ClusterMessages.proto index 469b67b0acd..9556dba9fbe 100644 --- a/src/protobuf/ClusterMessages.proto +++ b/src/protobuf/ClusterMessages.proto @@ -129,6 +129,7 @@ message Member { Exiting = 3; Down = 4; Removed = 5; + WeaklyUp = 6; } int32 addressIndex = 1; From c4580e1163d1cc0d36ecaf37ebee76f861e4b5d9 Mon Sep 17 00:00:00 2001 From: Nicola Sanitate Date: Thu, 21 Dec 2017 22:04:20 +0100 Subject: [PATCH 2/3] Update DeviceGroupQuery.cs (#3221) * Update DeviceGroupQuery.cs Fixed timing of the first change of behaviour, moved from OnReceive to Constructor method * Update DeviceGroupQuery.cs Fixed exit condition check on stillWaiting instead of repliesSoFar --- .../Tutorials/Tutorial4/DeviceGroupQuery.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/examples/Tutorials/Tutorial4/DeviceGroupQuery.cs b/docs/examples/Tutorials/Tutorial4/DeviceGroupQuery.cs index 27b5e4123bd..31b140931ba 100644 --- a/docs/examples/Tutorials/Tutorial4/DeviceGroupQuery.cs +++ b/docs/examples/Tutorials/Tutorial4/DeviceGroupQuery.cs @@ -18,6 +18,7 @@ public class DeviceGroupQuery : UntypedActor { private ICancelable queryTimeoutTimer; + #region query-state public DeviceGroupQuery(Dictionary actorToDeviceId, long requestId, IActorRef requester, TimeSpan timeout) { ActorToDeviceId = actorToDeviceId; @@ -26,6 +27,8 @@ public DeviceGroupQuery(Dictionary actorToDeviceId, long requ Timeout = timeout; queryTimeoutTimer = Context.System.Scheduler.ScheduleTellOnceCancelable(timeout, Self, CollectionTimeout.Instance, Self); + + Become(WaitingForReplies(new Dictionary(), new HashSet(ActorToDeviceId.Keys))); } protected override void PreStart() @@ -48,12 +51,6 @@ protected override void PostStop() public IActorRef Requester { get; } public TimeSpan Timeout { get; } - #region query-state - protected override void OnReceive(object message) - { - Become(WaitingForReplies(new Dictionary(), new HashSet(ActorToDeviceId.Keys))); - } - public UntypedReceive WaitingForReplies( Dictionary repliesSoFar, HashSet stillWaiting) @@ -106,7 +103,7 @@ public void ReceivedResponse( repliesSoFar.Add(deviceId, reading); - if (repliesSoFar.Count == 0) + if (stillWaiting.Count == 0) { Requester.Tell(new RespondAllTemperatures(RequestId, repliesSoFar)); Context.Stop(Self); @@ -116,7 +113,12 @@ public void ReceivedResponse( Context.Become(WaitingForReplies(repliesSoFar, stillWaiting)); } } - #endregion + #endregion + + protected override void OnReceive(object message) + { + + } public static Props Props(Dictionary actorToDeviceId, long requestId, IActorRef requester, TimeSpan timeout) => Akka.Actor.Props.Create(() => new DeviceGroupQuery(actorToDeviceId, requestId, requester, timeout)); From 78125b1887b2dc5295c9559c7a2d05988fba0531 Mon Sep 17 00:00:00 2001 From: Maxim Cherednik Date: Wed, 27 Dec 2017 19:02:19 +0100 Subject: [PATCH 3/3] Solution cleaning (#3216) (#3217) 1. old nuget folder removed 2. Project file references fixed --- src/Akka.sln | 141 +++++++++--------- .../Akka.Remote.TestKit.csproj | 2 +- .../Akka.Streams.Tests.TCK.csproj | 1 + .../Akka.Streams.Tests.csproj | 4 +- src/core/Akka.Streams/Akka.Streams.csproj | 2 +- .../Akka.Tests.Shared.Internals.csproj | 2 +- src/core/Akka.Tests/Akka.Tests.csproj | 4 +- 7 files changed, 75 insertions(+), 81 deletions(-) diff --git a/src/Akka.sln b/src/Akka.sln index 4dc2bf05b9f..14d444dc64c 100644 --- a/src/Akka.sln +++ b/src/Akka.sln @@ -5,47 +5,47 @@ VisualStudioVersion = 15.0.26730.15 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmark", "Benchmark", "{73108242-625A-4D7B-AA09-63375DBAE464}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PingPong", "benchmark\PingPong\PingPong.csproj", "{956F7D26-4505-4A26-86D0-73135BD35A93}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PingPong", "benchmark\PingPong\PingPong.csproj", "{956F7D26-4505-4A26-86D0-73135BD35A93}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{01167D3C-49C4-4CDE-9787-C176D139ACDD}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Remote.Tests", "core\Akka.Remote.Tests\Akka.Remote.Tests.csproj", "{95E921AB-1F5A-4AF9-B7FE-284E317A97F4}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Remote.Tests", "core\Akka.Remote.Tests\Akka.Remote.Tests.csproj", "{95E921AB-1F5A-4AF9-B7FE-284E317A97F4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.TestKit", "core\Akka.TestKit\Akka.TestKit.csproj", "{0D3CBAD0-BBDB-43E5-AFC4-ED1D3ECDC224}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.TestKit", "core\Akka.TestKit\Akka.TestKit.csproj", "{0D3CBAD0-BBDB-43E5-AFC4-ED1D3ECDC224}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Tests", "core\Akka.Tests\Akka.Tests.csproj", "{3F786C7D-70E3-4836-8B33-EC9A5AF72330}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Tests", "core\Akka.Tests\Akka.Tests.csproj", "{3F786C7D-70E3-4836-8B33-EC9A5AF72330}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Remote", "core\Akka.Remote\Akka.Remote.csproj", "{EA4FF8FD-7C53-49C8-B9AA-02E458B3E6A7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Remote", "core\Akka.Remote\Akka.Remote.csproj", "{EA4FF8FD-7C53-49C8-B9AA-02E458B3E6A7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka", "core\Akka\Akka.csproj", "{5DEDDF90-37F0-48D3-A0B0-A5CBD8A7E377}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka", "core\Akka\Akka.csproj", "{5DEDDF90-37F0-48D3-A0B0-A5CBD8A7E377}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.TestKit.Tests", "core\Akka.TestKit.Tests\Akka.TestKit.Tests.csproj", "{D2BED2D5-B152-48C1-9818-1097BECDDF98}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.TestKit.Tests", "core\Akka.TestKit.Tests\Akka.TestKit.Tests.csproj", "{D2BED2D5-B152-48C1-9818-1097BECDDF98}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Tests.Shared.Internals", "core\Akka.Tests.Shared.Internals\Akka.Tests.Shared.Internals.csproj", "{E636D23C-3432-4AA9-9A5D-5F29D33D3399}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Tests.Shared.Internals", "core\Akka.Tests.Shared.Internals\Akka.Tests.Shared.Internals.csproj", "{E636D23C-3432-4AA9-9A5D-5F29D33D3399}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster", "core\Akka.Cluster\Akka.Cluster.csproj", "{6AB00F61-269A-4501-B06A-026707F000A7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster", "core\Akka.Cluster\Akka.Cluster.csproj", "{6AB00F61-269A-4501-B06A-026707F000A7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.Tests", "core\Akka.Cluster.Tests\Akka.Cluster.Tests.csproj", "{C8D6A95C-50BF-4416-A212-86B18B87220D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Tests", "core\Akka.Cluster.Tests\Akka.Cluster.Tests.csproj", "{C8D6A95C-50BF-4416-A212-86B18B87220D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Remote.TestKit", "core\Akka.Remote.TestKit\Akka.Remote.TestKit.csproj", "{E5957C3E-2B1E-469F-A680-7953B4DEA31B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Remote.TestKit", "core\Akka.Remote.TestKit\Akka.Remote.TestKit.csproj", "{E5957C3E-2B1E-469F-A680-7953B4DEA31B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Remote.TestKit.Tests", "core\Akka.Remote.TestKit.Tests\Akka.Remote.TestKit.Tests.csproj", "{F338508B-FE01-4132-AC4A-FC00071EA4EB}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Remote.TestKit.Tests", "core\Akka.Remote.TestKit.Tests\Akka.Remote.TestKit.Tests.csproj", "{F338508B-FE01-4132-AC4A-FC00071EA4EB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.MultiNodeTestRunner", "core\Akka.MultiNodeTestRunner\Akka.MultiNodeTestRunner.csproj", "{C1113300-74F1-446A-9914-3020C842EDF1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.MultiNodeTestRunner", "core\Akka.MultiNodeTestRunner\Akka.MultiNodeTestRunner.csproj", "{C1113300-74F1-446A-9914-3020C842EDF1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.NodeTestRunner", "core\Akka.NodeTestRunner\Akka.NodeTestRunner.csproj", "{28520F30-2868-4BD3-9CAE-AC27226C24E3}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.NodeTestRunner", "core\Akka.NodeTestRunner\Akka.NodeTestRunner.csproj", "{28520F30-2868-4BD3-9CAE-AC27226C24E3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.Tests", "core\Akka.Persistence.Tests\Akka.Persistence.Tests.csproj", "{4492004A-A8D0-45B0-BACC-05BA2F38EC55}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Tests", "core\Akka.Persistence.Tests\Akka.Persistence.Tests.csproj", "{4492004A-A8D0-45B0-BACC-05BA2F38EC55}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.TCK", "core\Akka.Persistence.TCK\Akka.Persistence.TCK.csproj", "{AD9418B6-C452-4169-94FB-D43DE0BFA966}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.TCK", "core\Akka.Persistence.TCK\Akka.Persistence.TCK.csproj", "{AD9418B6-C452-4169-94FB-D43DE0BFA966}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence", "core\Akka.Persistence\Akka.Persistence.csproj", "{FCA84DEA-C118-424B-9EB8-34375DFEF18A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence", "core\Akka.Persistence\Akka.Persistence.csproj", "{FCA84DEA-C118-424B-9EB8-34375DFEF18A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.TCK.Tests", "core\Akka.Persistence.TCK.Tests\Akka.Persistence.TCK.Tests.csproj", "{E6CDDAC1-BD68-4C7B-9E6D-569AC6D50793}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.TCK.Tests", "core\Akka.Persistence.TCK.Tests\Akka.Persistence.TCK.Tests.csproj", "{E6CDDAC1-BD68-4C7B-9E6D-569AC6D50793}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.MultiNodeTestRunner.Shared.Tests", "core\Akka.MultiNodeTestRunner.Shared.Tests\Akka.MultiNodeTestRunner.Shared.Tests.csproj", "{91746A3F-21C6-4614-B0AB-A59310D75C51}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.MultiNodeTestRunner.Shared.Tests", "core\Akka.MultiNodeTestRunner.Shared.Tests\Akka.MultiNodeTestRunner.Shared.Tests.csproj", "{91746A3F-21C6-4614-B0AB-A59310D75C51}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.MultiNodeTestRunner.Shared", "core\Akka.MultiNodeTestRunner.Shared\Akka.MultiNodeTestRunner.Shared.csproj", "{964F0EC5-FBE6-47C5-8AE6-145114D5DB8C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.MultiNodeTestRunner.Shared", "core\Akka.MultiNodeTestRunner.Shared\Akka.MultiNodeTestRunner.Shared.csproj", "{964F0EC5-FBE6-47C5-8AE6-145114D5DB8C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Protobuf", "Protobuf", "{98CEB6FB-A277-42FA-A98E-99A8640B26FD}" ProjectSection(SolutionItems) = preProject @@ -59,13 +59,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Protobuf", "Protobuf", "{98 protobuf\WireFormats.proto = protobuf\WireFormats.proto EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{8A15341C-5596-4F4D-949D-2CD9A0006E12}" - ProjectSection(SolutionItems) = preProject - .nuget\NuGet.Config = .nuget\NuGet.Config - .nuget\nuget.exe = .nuget\nuget.exe - .nuget\NuGet.targets = .nuget\NuGet.targets - EndProjectSection -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{10C5B1E8-15B5-4EB3-81AE-1FC054FE1305}" ProjectSection(SolutionItems) = preProject ..\build.fsx = ..\build.fsx @@ -78,13 +71,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestKits", "TestKits", "{76 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Persistence", "Persistence", "{264C22A4-CAFC-41F6-B82C-4DDC5C196767}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.TestKit.Xunit2", "contrib\testkits\Akka.TestKit.Xunit2\Akka.TestKit.Xunit2.csproj", "{7DBD5C17-5E9D-40C4-9201-D092751532A7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.TestKit.Xunit2", "contrib\testkits\Akka.TestKit.Xunit2\Akka.TestKit.Xunit2.csproj", "{7DBD5C17-5E9D-40C4-9201-D092751532A7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.Sql.Common", "contrib\persistence\Akka.Persistence.Sql.Common\Akka.Persistence.Sql.Common.csproj", "{3B9E6211-9488-4DB5-B714-24248693B38F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Sql.Common", "contrib\persistence\Akka.Persistence.Sql.Common\Akka.Persistence.Sql.Common.csproj", "{3B9E6211-9488-4DB5-B714-24248693B38F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.Tests.MultiNode", "core\Akka.Cluster.Tests.MultiNode\Akka.Cluster.Tests.MultiNode.csproj", "{F0781BEA-5BA0-4AF0-BB15-E3F209B681F5}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Tests.MultiNode", "core\Akka.Cluster.Tests.MultiNode\Akka.Cluster.Tests.MultiNode.csproj", "{F0781BEA-5BA0-4AF0-BB15-E3F209B681F5}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PersistenceBenchmark", "benchmark\PersistenceBenchmark\PersistenceBenchmark.csproj", "{39E6F51F-FA1E-4C62-B8F8-19065DE6D55D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PersistenceBenchmark", "benchmark\PersistenceBenchmark\PersistenceBenchmark.csproj", "{39E6F51F-FA1E-4C62-B8F8-19065DE6D55D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A59BAE84-70E2-46A0-9E26-7413C103E2D7}" ProjectSection(SolutionItems) = preProject @@ -93,87 +86,87 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution NuGet.Config = NuGet.Config EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Remote.Tests.MultiNode", "core\Akka.Remote.Tests.MultiNode\Akka.Remote.Tests.MultiNode.csproj", "{C9105C76-B084-4DA1-9348-1C74A8F22F6B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Remote.Tests.MultiNode", "core\Akka.Remote.Tests.MultiNode\Akka.Remote.Tests.MultiNode.csproj", "{C9105C76-B084-4DA1-9348-1C74A8F22F6B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.Sqlite", "contrib\persistence\Akka.Persistence.Sqlite\Akka.Persistence.Sqlite.csproj", "{453EFD22-7C53-4887-9DBF-FCFC9172E909}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Sqlite", "contrib\persistence\Akka.Persistence.Sqlite\Akka.Persistence.Sqlite.csproj", "{453EFD22-7C53-4887-9DBF-FCFC9172E909}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.Sqlite.Tests", "contrib\persistence\Akka.Persistence.Sqlite.Tests\Akka.Persistence.Sqlite.Tests.csproj", "{7A832BBF-053E-4E9F-BD83-D988A0130CC8}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Sqlite.Tests", "contrib\persistence\Akka.Persistence.Sqlite.Tests\Akka.Persistence.Sqlite.Tests.csproj", "{7A832BBF-053E-4E9F-BD83-D988A0130CC8}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Serializers", "Serializers", "{0E55F1F8-E212-43D7-A0C0-ACEA9794B0D7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Serialization.TestKit", "contrib\serializers\Akka.Serialization.TestKit\Akka.Serialization.TestKit.csproj", "{CAA97041-CFC0-4081-9BD2-8B139E62A611}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Serialization.TestKit", "contrib\serializers\Akka.Serialization.TestKit\Akka.Serialization.TestKit.csproj", "{CAA97041-CFC0-4081-9BD2-8B139E62A611}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cluster", "Cluster", "{76F58DC4-19F1-43EF-A6E2-EC1CC8395AC5}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.Sharding", "contrib\cluster\Akka.Cluster.Sharding\Akka.Cluster.Sharding.csproj", "{A05C31E8-0246-46A1-B3BC-4D6FE7A9AA49}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Sharding", "contrib\cluster\Akka.Cluster.Sharding\Akka.Cluster.Sharding.csproj", "{A05C31E8-0246-46A1-B3BC-4D6FE7A9AA49}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.Tools", "contrib\cluster\Akka.Cluster.Tools\Akka.Cluster.Tools.csproj", "{5CF8A8BE-B634-473F-BB01-EBA878746BD4}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Tools", "contrib\cluster\Akka.Cluster.Tools\Akka.Cluster.Tools.csproj", "{5CF8A8BE-B634-473F-BB01-EBA878746BD4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.Tools.Tests", "contrib\cluster\Akka.Cluster.Tools.Tests\Akka.Cluster.Tools.Tests.csproj", "{9D8D62C7-7B4B-4CDF-8FE8-675DB71F6B21}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Tools.Tests", "contrib\cluster\Akka.Cluster.Tools.Tests\Akka.Cluster.Tools.Tests.csproj", "{9D8D62C7-7B4B-4CDF-8FE8-675DB71F6B21}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.Sharding.Tests", "contrib\cluster\Akka.Cluster.Sharding.Tests\Akka.Cluster.Sharding.Tests.csproj", "{B369F314-4D37-4AC1-B4FB-64FF671AF0BC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Sharding.Tests", "contrib\cluster\Akka.Cluster.Sharding.Tests\Akka.Cluster.Sharding.Tests.csproj", "{B369F314-4D37-4AC1-B4FB-64FF671AF0BC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Tests.Performance", "core\Akka.Tests.Performance\Akka.Tests.Performance.csproj", "{B17DEDCB-D2AA-472D-82A0-D242B711F488}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Tests.Performance", "core\Akka.Tests.Performance\Akka.Tests.Performance.csproj", "{B17DEDCB-D2AA-472D-82A0-D242B711F488}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Remote.Tests.Performance", "core\Akka.Remote.Tests.Performance\Akka.Remote.Tests.Performance.csproj", "{453DD4B1-64B8-4B50-BFDA-3489E32D30D8}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Remote.Tests.Performance", "core\Akka.Remote.Tests.Performance\Akka.Remote.Tests.Performance.csproj", "{453DD4B1-64B8-4B50-BFDA-3489E32D30D8}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Streams", "core\Akka.Streams\Akka.Streams.csproj", "{6180A876-AE4A-41E2-A08F-84FDEA0C8A0E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Streams", "core\Akka.Streams\Akka.Streams.csproj", "{6180A876-AE4A-41E2-A08F-84FDEA0C8A0E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Streams.Tests", "core\Akka.Streams.Tests\Akka.Streams.Tests.csproj", "{9F63102D-8270-4B83-B2B6-BDD4EAC1FEB7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Streams.Tests", "core\Akka.Streams.Tests\Akka.Streams.Tests.csproj", "{9F63102D-8270-4B83-B2B6-BDD4EAC1FEB7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Streams.TestKit", "core\Akka.Streams.TestKit\Akka.Streams.TestKit.csproj", "{AC70BF13-890B-4A06-A269-D0B301F463DF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Streams.TestKit", "core\Akka.Streams.TestKit\Akka.Streams.TestKit.csproj", "{AC70BF13-890B-4A06-A269-D0B301F463DF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.API.Tests", "core\Akka.API.Tests\Akka.API.Tests.csproj", "{F72BE71A-2BE3-413D-A3D9-C7FDBB4E5F08}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.API.Tests", "core\Akka.API.Tests\Akka.API.Tests.csproj", "{F72BE71A-2BE3-413D-A3D9-C7FDBB4E5F08}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Streams.TestKit.Tests", "core\Akka.Streams.TestKit.Tests\Akka.Streams.TestKit.Tests.csproj", "{46EA9956-913F-4E65-9902-28A5EDD9CDB3}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Streams.TestKit.Tests", "core\Akka.Streams.TestKit.Tests\Akka.Streams.TestKit.Tests.csproj", "{46EA9956-913F-4E65-9902-28A5EDD9CDB3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.TestKit", "core\Akka.Cluster.TestKit\Akka.Cluster.TestKit.csproj", "{B32850D2-E9CB-4638-83A4-164907595E56}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.TestKit", "core\Akka.Cluster.TestKit\Akka.Cluster.TestKit.csproj", "{B32850D2-E9CB-4638-83A4-164907595E56}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.Query", "core\Akka.Persistence.Query\Akka.Persistence.Query.csproj", "{92AB2788-E008-40D0-8B54-0C95B3CF3404}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Query", "core\Akka.Persistence.Query\Akka.Persistence.Query.csproj", "{92AB2788-E008-40D0-8B54-0C95B3CF3404}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.Query.Tests", "core\Akka.Persistence.Query.Tests\Akka.Persistence.Query.Tests.csproj", "{C01FE575-10B5-4072-8EF9-66FA7CD86F6F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Query.Tests", "core\Akka.Persistence.Query.Tests\Akka.Persistence.Query.Tests.csproj", "{C01FE575-10B5-4072-8EF9-66FA7CD86F6F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Streams.Tests.Performance", "core\Akka.Streams.Tests.Performance\Akka.Streams.Tests.Performance.csproj", "{F5934093-4B7C-4303-9E27-60B4021C05B2}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Streams.Tests.Performance", "core\Akka.Streams.Tests.Performance\Akka.Streams.Tests.Performance.csproj", "{F5934093-4B7C-4303-9E27-60B4021C05B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.Query.Sql", "contrib\persistence\Akka.Persistence.Query.Sql\Akka.Persistence.Query.Sql.csproj", "{3CBD3880-0655-44CC-AD81-77E8CADFCC3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Query.Sql", "contrib\persistence\Akka.Persistence.Query.Sql\Akka.Persistence.Query.Sql.csproj", "{3CBD3880-0655-44CC-AD81-77E8CADFCC3E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.Tools.Tests.MultiNode", "contrib\cluster\Akka.Cluster.Tools.Tests.MultiNode\Akka.Cluster.Tools.Tests.MultiNode.csproj", "{666698AB-85BC-4C91-894C-CBB4316DC1A4}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Tools.Tests.MultiNode", "contrib\cluster\Akka.Cluster.Tools.Tests.MultiNode\Akka.Cluster.Tools.Tests.MultiNode.csproj", "{666698AB-85BC-4C91-894C-CBB4316DC1A4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.Sql.TestKit", "contrib\persistence\Akka.Persistence.Sql.TestKit\Akka.Persistence.Sql.TestKit.csproj", "{14502A16-2B6F-4728-8A98-ED5AF45FC515}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Sql.TestKit", "contrib\persistence\Akka.Persistence.Sql.TestKit\Akka.Persistence.Sql.TestKit.csproj", "{14502A16-2B6F-4728-8A98-ED5AF45FC515}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Streams.Tests.TCK", "core\Akka.Streams.Tests.TCK\Akka.Streams.Tests.TCK.csproj", "{805908F6-8792-47C0-8E4F-4DB4C5736A47}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Streams.Tests.TCK", "core\Akka.Streams.Tests.TCK\Akka.Streams.Tests.TCK.csproj", "{805908F6-8792-47C0-8E4F-4DB4C5736A47}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.Sharding.Tests.MultiNode", "contrib\cluster\Akka.Cluster.Sharding.Tests.MultiNode\Akka.Cluster.Sharding.Tests.MultiNode.csproj", "{F79A5E87-1DB5-4D76-9B14-382F8C536DA6}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Sharding.Tests.MultiNode", "contrib\cluster\Akka.Cluster.Sharding.Tests.MultiNode\Akka.Cluster.Sharding.Tests.MultiNode.csproj", "{F79A5E87-1DB5-4D76-9B14-382F8C536DA6}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.DistributedData", "contrib\cluster\Akka.DistributedData\Akka.DistributedData.csproj", "{59CFFC88-8A73-445D-B191-281E40BE9421}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.DistributedData", "contrib\cluster\Akka.DistributedData\Akka.DistributedData.csproj", "{59CFFC88-8A73-445D-B191-281E40BE9421}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.DistributedData.Tests", "contrib\cluster\Akka.DistributedData.Tests\Akka.DistributedData.Tests.csproj", "{0DBF3D66-6E5E-4A89-AA3D-674B92FE81B7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.DistributedData.Tests", "contrib\cluster\Akka.DistributedData.Tests\Akka.DistributedData.Tests.csproj", "{0DBF3D66-6E5E-4A89-AA3D-674B92FE81B7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.DistributedData.Tests.MultiNode", "contrib\cluster\Akka.DistributedData.Tests.MultiNode\Akka.DistributedData.Tests.MultiNode.csproj", "{53A657B3-D3CD-461E-9759-664331218060}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.DistributedData.Tests.MultiNode", "contrib\cluster\Akka.DistributedData.Tests.MultiNode\Akka.DistributedData.Tests.MultiNode.csproj", "{53A657B3-D3CD-461E-9759-664331218060}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Serialization.Hyperion", "contrib\serializers\Akka.Serialization.Hyperion\Akka.Serialization.Hyperion.csproj", "{6C995BF6-1F8D-40EE-B608-68E36EA6A6F8}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Serialization.Hyperion", "contrib\serializers\Akka.Serialization.Hyperion\Akka.Serialization.Hyperion.csproj", "{6C995BF6-1F8D-40EE-B608-68E36EA6A6F8}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Serialization.Hyperion.Tests", "contrib\serializers\Akka.Serialization.Hyperion.Tests\Akka.Serialization.Hyperion.Tests.csproj", "{E3549E17-7206-44F0-A322-EDC058A0498F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Serialization.Hyperion.Tests", "contrib\serializers\Akka.Serialization.Hyperion.Tests\Akka.Serialization.Hyperion.Tests.csproj", "{E3549E17-7206-44F0-A322-EDC058A0498F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Transports", "Transports", "{6AD34FA4-7584-454D-ACD4-A8911E0BDB00}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Remote.Transport.Helios", "contrib\transports\Akka.Remote.Transport.Helios\Akka.Remote.Transport.Helios.csproj", "{29FEAABC-E326-450A-9008-B5FCECF0115F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Remote.Transport.Helios", "contrib\transports\Akka.Remote.Transport.Helios\Akka.Remote.Transport.Helios.csproj", "{29FEAABC-E326-450A-9008-B5FCECF0115F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DependencyInjection", "DependencyInjection", "{48845655-5E60-40AB-A798-F118CC1CF510}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.DI.Core", "contrib\dependencyinjection\Akka.DI.Core\Akka.DI.Core.csproj", "{3DCFADA2-02DF-41AD-A907-F805B86A5DFE}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.DI.Core", "contrib\dependencyinjection\Akka.DI.Core\Akka.DI.Core.csproj", "{3DCFADA2-02DF-41AD-A907-F805B86A5DFE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.DI.TestKit", "contrib\dependencyinjection\Akka.DI.TestKit\Akka.DI.TestKit.csproj", "{539317E7-EEEF-4BE5-A12D-6BB048E7A1E3}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.DI.TestKit", "contrib\dependencyinjection\Akka.DI.TestKit\Akka.DI.TestKit.csproj", "{539317E7-EEEF-4BE5-A12D-6BB048E7A1E3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.TestKit.Xunit", "contrib\testkits\Akka.TestKit.Xunit\Akka.TestKit.Xunit.csproj", "{E7A836C1-42D3-4ADC-81C6-C6C5398CC740}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.TestKit.Xunit", "contrib\testkits\Akka.TestKit.Xunit\Akka.TestKit.Xunit.csproj", "{E7A836C1-42D3-4ADC-81C6-C6C5398CC740}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.Tests.Performance", "core\Akka.Cluster.Tests.Performance\Akka.Cluster.Tests.Performance.csproj", "{94C10096-C33E-404E-B0FB-F8535512A952}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Tests.Performance", "core\Akka.Cluster.Tests.Performance\Akka.Cluster.Tests.Performance.csproj", "{94C10096-C33E-404E-B0FB-F8535512A952}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.DistributedData.LightningDB", "contrib\cluster\Akka.DistributedData.LightningDB\Akka.DistributedData.LightningDB.csproj", "{99CCB7CA-E1EE-4497-BF52-2200A0EC5CB1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.DistributedData.LightningDB", "contrib\cluster\Akka.DistributedData.LightningDB\Akka.DistributedData.LightningDB.csproj", "{99CCB7CA-E1EE-4497-BF52-2200A0EC5CB1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpawnBenchmark", "benchmark\SpawnBenchmark\SpawnBenchmark.csproj", "{DA4BDE1E-1ACA-482A-9329-952C3E36F97D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpawnBenchmark", "benchmark\SpawnBenchmark\SpawnBenchmark.csproj", "{DA4BDE1E-1ACA-482A-9329-952C3E36F97D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RemotePingPong", "benchmark\RemotePingPong\RemotePingPong.csproj", "{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RemotePingPong", "benchmark\RemotePingPong\RemotePingPong.csproj", "{5AA81B79-34DD-4DD7-9D40-A5CA389786DF}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{D3AF8295-AEB5-4324-AA82-FCC0014AC310}" EndProject @@ -181,19 +174,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cluster", "Cluster", "{C50E EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ClusterSharding.Node", "ClusterSharding.Node", "{820CFBF7-E165-4ADA-B821-E6A0A81DFE84}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClusterSharding.Node", "examples\Cluster\ClusterSharding\ClusterSharding.Node\ClusterSharding.Node.csproj", "{3C6EB4EF-3726-432F-812E-07828876418B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClusterSharding.Node", "examples\Cluster\ClusterSharding\ClusterSharding.Node\ClusterSharding.Node.csproj", "{3C6EB4EF-3726-432F-812E-07828876418B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Chat", "Chat", "{AF50BDA2-EA1C-4694-9B0C-CB5D50024181}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatMessages", "examples\Chat\ChatMessages\ChatMessages.csproj", "{6389B968-FFBE-44AF-9016-687E837D555B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatMessages", "examples\Chat\ChatMessages\ChatMessages.csproj", "{6389B968-FFBE-44AF-9016-687E837D555B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatServer", "examples\Chat\ChatServer\ChatServer.csproj", "{91B73868-F504-45F2-B49F-9F967D692230}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatServer", "examples\Chat\ChatServer\ChatServer.csproj", "{91B73868-F504-45F2-B49F-9F967D692230}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatClient", "examples\Chat\ChatClient\ChatClient.csproj", "{81D89DA8-A58E-41A8-9558-8289ACE8BF88}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatClient", "examples\Chat\ChatClient\ChatClient.csproj", "{81D89DA8-A58E-41A8-9558-8289ACE8BF88}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.Cluster.Simple", "examples\Cluster\Samples.Cluster.Simple\Samples.Cluster.Simple.csproj", "{C78223F9-A4C8-4DC9-A4A0-CAEC3611E5B9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Cluster.Simple", "examples\Cluster\Samples.Cluster.Simple\Samples.Cluster.Simple.csproj", "{C78223F9-A4C8-4DC9-A4A0-CAEC3611E5B9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.Cluster.Transformation", "examples\Cluster\Roles\Samples.Cluster.Transformation\Samples.Cluster.Transformation.csproj", "{01B074DB-67C8-4600-8CE2-DAAAFC052261}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Cluster.Transformation", "examples\Cluster\Roles\Samples.Cluster.Transformation\Samples.Cluster.Transformation.csproj", "{01B074DB-67C8-4600-8CE2-DAAAFC052261}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj index 332ad3e22f8..7b37a900d3f 100644 --- a/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj +++ b/src/core/Akka.Remote.TestKit/Akka.Remote.TestKit.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/core/Akka.Streams.Tests.TCK/Akka.Streams.Tests.TCK.csproj b/src/core/Akka.Streams.Tests.TCK/Akka.Streams.Tests.TCK.csproj index 24ad0d2993b..eba5ce929ed 100644 --- a/src/core/Akka.Streams.Tests.TCK/Akka.Streams.Tests.TCK.csproj +++ b/src/core/Akka.Streams.Tests.TCK/Akka.Streams.Tests.TCK.csproj @@ -1,4 +1,5 @@  + Akka.Streams.Tests net452 diff --git a/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj b/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj index 1078f4487ca..60a7b72c1cf 100644 --- a/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj +++ b/src/core/Akka.Streams.Tests/Akka.Streams.Tests.csproj @@ -30,8 +30,8 @@ - - + + diff --git a/src/core/Akka.Streams/Akka.Streams.csproj b/src/core/Akka.Streams/Akka.Streams.csproj index 8a4c8938ac0..6c5fab2efe6 100644 --- a/src/core/Akka.Streams/Akka.Streams.csproj +++ b/src/core/Akka.Streams/Akka.Streams.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj b/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj index 0143c9342da..e9d89495c1f 100644 --- a/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj +++ b/src/core/Akka.Tests.Shared.Internals/Akka.Tests.Shared.Internals.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/core/Akka.Tests/Akka.Tests.csproj b/src/core/Akka.Tests/Akka.Tests.csproj index 8141a927c62..bd521e79bbf 100644 --- a/src/core/Akka.Tests/Akka.Tests.csproj +++ b/src/core/Akka.Tests/Akka.Tests.csproj @@ -27,8 +27,8 @@ - - + +