@@ -66,14 +66,14 @@ extension Cluster {
66
66
///
67
67
/// This operation is guaranteed to return a member if it was added to the membership UNLESS the member has been `.removed`
68
68
/// and dropped which happens only after an extended period of time. // FIXME: That period of time is not implemented
69
- public func uniqueMember ( _ node: Cluster . Node ) -> Cluster . Member ? {
69
+ public func member ( _ node: Cluster . Node ) -> Cluster . Member ? {
70
70
self . _members [ node]
71
71
}
72
72
73
73
/// Picks "first", in terms of least progressed among its lifecycle member in presence of potentially multiple members
74
74
/// for a non-unique `Node`. In practice, this happens when an existing node is superseded by a "replacement", and the
75
75
/// previous node becomes immediately down.
76
- public func member ( _ endpoint: Cluster . Endpoint ) -> Cluster . Member ? {
76
+ public func anyMember ( forEndpoint endpoint: Cluster . Endpoint ) -> Cluster . Member ? {
77
77
self . _members. values. sorted ( by: Cluster . MemberStatus. lifecycleOrdering) . first ( where: { $0. node. endpoint == endpoint } )
78
78
}
79
79
@@ -90,14 +90,22 @@ extension Cluster {
90
90
self . _members. count
91
91
}
92
92
93
- /// More efficient than using `members(atLeast:) ` followed by a `.count`
93
+ /// More efficient than using `` members(atLeast:reachability:)` ` followed by a `.count`
94
94
public func count( atLeast status: Cluster . MemberStatus ) -> Int {
95
95
self . _members. values
96
96
. lazy
97
97
. filter { member in status <= member. status }
98
98
. count
99
99
}
100
100
101
+ /// More efficient than using ``members(atMost:reachability:)`` followed by a `.count`
102
+ public func count( atMost status: Cluster . MemberStatus ) -> Int {
103
+ self . _members. values
104
+ . lazy
105
+ . filter { member in member. status <= status }
106
+ . count
107
+ }
108
+
101
109
/// More efficient than using `members(withStatus:)` followed by a `.count`
102
110
public func count( withStatus status: Cluster . MemberStatus ) -> Int {
103
111
self . _members. values
@@ -153,6 +161,13 @@ extension Cluster {
153
161
}
154
162
}
155
163
164
+ /// Returns all members that are part of this membership, and have ``Cluster/MemberStatus`` that is *at most*
165
+ /// the passed in `status` and `reachability`. See ``Cluster/MemberStatus`` to learn more about the meaning of "at most".
166
+ ///
167
+ /// - Parameters:
168
+ /// - status: "at most" status for which to check the members for
169
+ /// - reachability: optional reachability that the members will be filtered by
170
+ /// - Returns: array of members matching those checks. Can be empty.
156
171
public func members( atMost status: Cluster . MemberStatus , reachability: Cluster . MemberReachability ? = nil ) -> [ Cluster . Member ] {
157
172
if status == . removed, reachability == nil {
158
173
return Array ( self . _members. values)
@@ -189,7 +204,7 @@ extension Cluster {
189
204
/// Certain actions can only be performed by the "leader" of a group.
190
205
public internal( set) var leader : Cluster . Member ? {
191
206
get {
192
- self . _leaderNode. flatMap { self . uniqueMember ( $0) }
207
+ self . _leaderNode. flatMap { self . member ( $0) }
193
208
}
194
209
set {
195
210
self . _leaderNode = newValue? . node
@@ -223,6 +238,21 @@ extension Cluster {
223
238
}
224
239
}
225
240
241
+ extension Cluster . Membership : Sequence {
242
+ public struct Iterator : IteratorProtocol {
243
+ public typealias Element = Cluster . Member
244
+ internal var it : Dictionary < Cluster . Node , Cluster . Member > . Values . Iterator
245
+
246
+ public mutating func next( ) -> Cluster . Member ? {
247
+ self . it. next ( )
248
+ }
249
+ }
250
+
251
+ public func makeIterator( ) -> Iterator {
252
+ . init( it: self . _members. values. makeIterator ( ) )
253
+ }
254
+ }
255
+
226
256
// Implementation notes: Membership/Member equality
227
257
//
228
258
// Membership equality is special, as it manually DOES take into account the Member's states (status, reachability),
@@ -300,7 +330,7 @@ extension Cluster.Membership {
300
330
return self . removeCompletely ( change. node)
301
331
}
302
332
303
- if let knownUnique = self . uniqueMember ( change. node) {
333
+ if let knownUnique = self . member ( change. node) {
304
334
// it is known uniquely, so we just update its status
305
335
return self . mark ( knownUnique. node, as: change. status)
306
336
}
@@ -311,7 +341,7 @@ extension Cluster.Membership {
311
341
return nil
312
342
}
313
343
314
- if let previousMember = self . member ( change. node. endpoint) {
344
+ if let previousMember = self . anyMember ( forEndpoint : change. node. endpoint) {
315
345
// we are joining "over" an existing incarnation of a node; causing the existing node to become .down immediately
316
346
if previousMember. status < . down {
317
347
_ = self . mark ( previousMember. node, as: . down)
@@ -398,7 +428,7 @@ extension Cluster.Membership {
398
428
///
399
429
/// If the membership not aware of this address the update is treated as a no-op.
400
430
public mutating func mark( _ node: Cluster . Node , as status: Cluster . MemberStatus ) -> Cluster . MembershipChange ? {
401
- if let existingExactMember = self . uniqueMember ( node) {
431
+ if let existingExactMember = self . member ( node) {
402
432
guard existingExactMember. status < status else {
403
433
// this would be a "move backwards" which we do not do; membership only moves forward
404
434
return nil
@@ -412,7 +442,7 @@ extension Cluster.Membership {
412
442
self . _members [ existingExactMember. node] = updatedMember
413
443
414
444
return Cluster . MembershipChange ( member: existingExactMember, toStatus: status)
415
- } else if let beingReplacedMember = self . member ( node. endpoint) {
445
+ } else if let beingReplacedMember = self . anyMember ( forEndpoint : node. endpoint) {
416
446
// We did not get a member by exact Cluster.Node match, but we got one by Node match...
417
447
// this means this new node that we are trying to mark is a "replacement" and the `beingReplacedNode` must be .downed!
418
448
@@ -619,14 +649,14 @@ extension Cluster.Membership {
619
649
// TODO: diffing is not super well tested, may lose up numbers
620
650
static func _diff( from: Cluster . Membership , to: Cluster . Membership ) -> MembershipDiff {
621
651
var entries : [ Cluster . MembershipChange ] = [ ]
622
- entries. reserveCapacity ( max ( from. _members. count, to. _members. count) )
652
+ entries. reserveCapacity ( Swift . max ( from. _members. count, to. _members. count) )
623
653
624
654
// TODO: can likely be optimized more
625
655
var to = to
626
656
627
657
// iterate over the original member set, and remove from the `to` set any seen members
628
658
for member in from. _members. values {
629
- if let toMember = to. uniqueMember ( member. node) {
659
+ if let toMember = to. member ( member. node) {
630
660
to. _members. removeValue ( forKey: member. node)
631
661
if member. status != toMember. status {
632
662
entries. append ( . init( member: member, toStatus: toMember. status) )
0 commit comments