public ClusterMembershipService( MembershipTableManager membershipTableManager, ILogger <ClusterMembershipService> log, IFatalErrorHandler fatalErrorHandler) { this.snapshot = membershipTableManager.MembershipTableSnapshot.CreateClusterMembershipSnapshot(); this.updates = new AsyncEnumerable <ClusterMembershipSnapshot>( (previous, proposed) => proposed.Version == MembershipVersion.MinValue || proposed.Version > previous.Version, this.snapshot) { OnPublished = update => Interlocked.Exchange(ref this.snapshot, update) }; this.membershipTableManager = membershipTableManager; this.log = log; this.fatalErrorHandler = fatalErrorHandler; }
/// <summary> /// Returns a <see cref="ClusterMembershipUpdate"/> which represents the change in cluster membership from the provided snapshot to this instance. /// </summary> /// <returns>A <see cref="ClusterMembershipUpdate"/> which represents the change in cluster membership from the provided snapshot to this instance.</returns> public ClusterMembershipUpdate CreateUpdate(ClusterMembershipSnapshot previous) { if (previous is null) { throw new ArgumentNullException(nameof(previous)); } if (this.Version < previous.Version) { throw new ArgumentException($"Argument must have a previous version to the current instance. Expected <= {this.Version}, encountered {previous.Version}", nameof(previous)); } if (this.Version == previous.Version) { return(new ClusterMembershipUpdate(this, ImmutableArray <ClusterMember> .Empty)); } var changes = ImmutableHashSet.CreateBuilder <ClusterMember>(); foreach (var entry in this.Members) { // Include any entry which is new or has changed state. if (!previous.Members.TryGetValue(entry.Key, out var previousEntry) || previousEntry.Status != entry.Value.Status) { changes.Add(entry.Value); } } // Handle entries which were removed entirely. foreach (var entry in previous.Members) { if (!this.Members.TryGetValue(entry.Key, out _)) { changes.Add(new ClusterMember(entry.Key, SiloStatus.Dead, entry.Value.Name)); } } return(new ClusterMembershipUpdate(this, changes.ToImmutableArray())); }
/// <summary> /// Initializes a new instance of the <see cref="ClusterMembershipUpdate"/> class. /// </summary> /// <param name="snapshot">The snapshot.</param> /// <param name="changes">The changes.</param> public ClusterMembershipUpdate(ClusterMembershipSnapshot snapshot, ImmutableArray <ClusterMember> changes) { this.Snapshot = snapshot; this.Changes = changes; }