@@ -45,227 +45,4 @@ final class ActorSingletonPluginTests: ActorSystemTestBase {
4545
4646 try replyProbe. expectMessage ( " Hi Charlie! " )
4747 }
48-
49- func test_singletonByClusterLeadership( ) throws {
50- try shouldNotThrow {
51- var singletonSettings = ActorSingletonSettings ( name: GreeterSingleton . name)
52- singletonSettings. allocationStrategy = . byLeadership
53-
54- let first = self . setUpNode ( " first " ) { settings in
55- settings. cluster. node. port = 7111
56- settings. cluster. autoLeaderElection = . lowestAddress( minNumberOfMembers: 3 )
57-
58- settings += ActorSingleton ( settings: singletonSettings, GreeterSingleton . makeBehavior ( instance: GreeterSingleton ( " Hello-1 " ) ) )
59-
60- settings. serialization. registerCodable ( for: GreeterSingleton . Message. self, underId: 10001 )
61- }
62- let second = self . setUpNode ( " second " ) { settings in
63- settings. cluster. node. port = 8222
64- settings. cluster. autoLeaderElection = . lowestAddress( minNumberOfMembers: 3 )
65-
66- settings += ActorSingleton ( settings: singletonSettings, GreeterSingleton . makeBehavior ( instance: GreeterSingleton ( " Hello-2 " ) ) )
67-
68- settings. serialization. registerCodable ( for: GreeterSingleton . Message. self, underId: 10001 )
69- }
70- let third = self . setUpNode ( " third " ) { settings in
71- settings. cluster. node. port = 9333
72- settings. cluster. autoLeaderElection = . lowestAddress( minNumberOfMembers: 3 )
73-
74- settings += ActorSingleton ( settings: singletonSettings, GreeterSingleton . makeBehavior ( instance: GreeterSingleton ( " Hello-3 " ) ) )
75-
76- settings. serialization. registerCodable ( for: GreeterSingleton . Message. self, underId: 10001 )
77- }
78-
79- first. cluster. join ( node: second. cluster. node. node)
80- third. cluster. join ( node: second. cluster. node. node)
81-
82- // `first` will be the leader (lowest address) and runs the singleton
83- try self . ensureNodes ( . up, within: . seconds( 10 ) , systems: first, second, third)
84-
85- let replyProbe1 = self . testKit ( first) . spawnTestProbe ( expecting: String . self)
86- let ref1 = try first. singleton. ref ( name: GreeterSingleton . name, of: GreeterSingleton . Message. self)
87- ref1. tell ( . greet( name: " Charlie " , _replyTo: replyProbe1. ref) )
88-
89- let replyProbe2 = self . testKit ( second) . spawnTestProbe ( expecting: String . self)
90- let ref2 = try second. singleton. ref ( name: GreeterSingleton . name, of: GreeterSingleton . Message. self)
91- ref2. tell ( . greet( name: " Charlie " , _replyTo: replyProbe2. ref) )
92-
93- let replyProbe3 = self . testKit ( third) . spawnTestProbe ( expecting: String . self)
94- let ref3 = try third. singleton. ref ( name: GreeterSingleton . name, of: GreeterSingleton . Message. self)
95- ref3. tell ( . greet( name: " Charlie " , _replyTo: replyProbe3. ref) )
96-
97- try replyProbe1. expectMessage ( " Hello-1 Charlie! " )
98- try replyProbe2. expectMessage ( " Hello-1 Charlie! " )
99- try replyProbe3. expectMessage ( " Hello-1 Charlie! " )
100- }
101- }
102-
103- func test_singletonByClusterLeadership_stashMessagesIfNoLeader( ) throws {
104- try shouldNotThrow {
105- var singletonSettings = ActorSingletonSettings ( name: GreeterSingleton . name)
106- singletonSettings. allocationStrategy = . byLeadership
107-
108- let first = self . setUpNode ( " first " ) { settings in
109- settings. cluster. node. port = 7111
110- settings. cluster. autoLeaderElection = . lowestAddress( minNumberOfMembers: 3 )
111-
112- settings += ActorSingleton ( settings: singletonSettings, GreeterSingleton . makeBehavior ( instance: GreeterSingleton ( " Hello-1 " ) ) )
113-
114- settings. serialization. registerCodable ( for: GreeterSingleton . Message. self, underId: 10001 )
115- }
116- let second = self . setUpNode ( " second " ) { settings in
117- settings. cluster. node. port = 8222
118- settings. cluster. autoLeaderElection = . lowestAddress( minNumberOfMembers: 3 )
119-
120- settings += ActorSingleton ( settings: singletonSettings, GreeterSingleton . makeBehavior ( instance: GreeterSingleton ( " Hello-2 " ) ) )
121-
122- settings. serialization. registerCodable ( for: GreeterSingleton . Message. self, underId: 10001 )
123- }
124- let third = self . setUpNode ( " third " ) { settings in
125- settings. cluster. node. port = 9333
126- settings. cluster. autoLeaderElection = . lowestAddress( minNumberOfMembers: 3 )
127-
128- settings += ActorSingleton ( settings: singletonSettings, GreeterSingleton . makeBehavior ( instance: GreeterSingleton ( " Hello-3 " ) ) )
129-
130- settings. serialization. registerCodable ( for: GreeterSingleton . Message. self, underId: 10001 )
131- }
132-
133- // No leader so singleton is not available, messages sent should be stashed
134- let replyProbe1 = self . testKit ( first) . spawnTestProbe ( expecting: String . self)
135- let ref1 = try first. singleton. ref ( name: GreeterSingleton . name, of: GreeterSingleton . Message. self)
136- ref1. tell ( . greet( name: " Charlie " , _replyTo: replyProbe1. ref) )
137-
138- let replyProbe2 = self . testKit ( second) . spawnTestProbe ( expecting: String . self)
139- let ref2 = try second. singleton. ref ( name: GreeterSingleton . name, of: GreeterSingleton . Message. self)
140- ref2. tell ( . greet( name: " Charlie " , _replyTo: replyProbe2. ref) )
141-
142- let replyProbe3 = self . testKit ( third) . spawnTestProbe ( expecting: String . self)
143- let ref3 = try third. singleton. ref ( name: GreeterSingleton . name, of: GreeterSingleton . Message. self)
144- ref3. tell ( . greet( name: " Charlie " , _replyTo: replyProbe3. ref) )
145-
146- try replyProbe1. expectNoMessage ( for: . milliseconds( 200 ) )
147- try replyProbe2. expectNoMessage ( for: . milliseconds( 200 ) )
148- try replyProbe3. expectNoMessage ( for: . milliseconds( 200 ) )
149-
150- first. cluster. join ( node: second. cluster. node. node)
151- third. cluster. join ( node: second. cluster. node. node)
152-
153- // `first` becomes the leader (lowest address) and runs the singleton
154- try self . ensureNodes ( . up, within: . seconds( 10 ) , systems: first, second, third)
155-
156- try replyProbe1. expectMessage ( " Hello-1 Charlie! " )
157- try replyProbe2. expectMessage ( " Hello-1 Charlie! " )
158- try replyProbe3. expectMessage ( " Hello-1 Charlie! " )
159- }
160- }
161-
162- func test_singletonByClusterLeadership_withLeaderChange( ) throws {
163- try shouldNotThrow {
164- var singletonSettings = ActorSingletonSettings ( name: GreeterSingleton . name)
165- singletonSettings. allocationStrategy = . byLeadership
166-
167- let first = self . setUpNode ( " first " ) { settings in
168- settings. cluster. node. port = 7111
169- settings. cluster. autoLeaderElection = . lowestAddress( minNumberOfMembers: 3 )
170- settings. serialization. registerCodable ( for: GreeterSingleton . Message. self, underId: 10001 )
171-
172- settings += ActorSingleton ( settings: singletonSettings, GreeterSingleton . makeBehavior ( instance: GreeterSingleton ( " Hello-1 " ) ) )
173- }
174- let second = self . setUpNode ( " second " ) { settings in
175- settings. cluster. node. port = 8222
176- settings. cluster. autoLeaderElection = . lowestAddress( minNumberOfMembers: 3 )
177- settings. serialization. registerCodable ( for: GreeterSingleton . Message. self, underId: 10001 )
178-
179- settings += ActorSingleton ( settings: singletonSettings, GreeterSingleton . makeBehavior ( instance: GreeterSingleton ( " Hello-2 " ) ) )
180- }
181- let third = self . setUpNode ( " third " ) { settings in
182- settings. cluster. node. port = 9333
183- settings. cluster. autoLeaderElection = . lowestAddress( minNumberOfMembers: 3 )
184- settings. serialization. registerCodable ( for: GreeterSingleton . Message. self, underId: 10001 )
185-
186- settings += ActorSingleton ( settings: singletonSettings, GreeterSingleton . makeBehavior ( instance: GreeterSingleton ( " Hello-3 " ) ) )
187- }
188- let fourth = self . setUpNode ( " fourth " ) { settings in
189- settings. cluster. node. port = 7444
190- settings. cluster. autoLeaderElection = . lowestAddress( minNumberOfMembers: 3 )
191- settings. serialization. registerCodable ( for: GreeterSingleton . Message. self, underId: 10001 )
192-
193- settings += ActorSingleton ( settings: singletonSettings, GreeterSingleton . makeBehavior ( instance: GreeterSingleton ( " Hello-4 " ) ) )
194- }
195-
196- try self . joinNodes ( node: first, with: second)
197- try self . joinNodes ( node: third, with: second)
198- try self . ensureNodes ( . up, within: . seconds( 10 ) , systems: first, second, third)
199-
200- let replyProbe1 = self . testKit ( first) . spawnTestProbe ( expecting: String . self)
201- let ref1 = try first. singleton. ref ( name: GreeterSingleton . name, of: GreeterSingleton . Message. self)
202- ref1. tell ( . greet( name: " Charlie " , _replyTo: replyProbe1. ref) )
203-
204- let replyProbe2 = self . testKit ( second) . spawnTestProbe ( expecting: String . self)
205- let ref2 = try second. singleton. ref ( name: GreeterSingleton . name, of: GreeterSingleton . Message. self)
206- ref2. tell ( . greet( name: " Charlie " , _replyTo: replyProbe2. ref) )
207-
208- let replyProbe3 = self . testKit ( third) . spawnTestProbe ( expecting: String . self)
209- let ref3 = try third. singleton. ref ( name: GreeterSingleton . name, of: GreeterSingleton . Message. self)
210- ref3. tell ( . greet( name: " Charlie " , _replyTo: replyProbe3. ref) )
211-
212- // `first` has the lowest address so it should be the leader and singleton
213- try replyProbe1. expectMessage ( " Hello-1 Charlie! " )
214- try replyProbe2. expectMessage ( " Hello-1 Charlie! " )
215- try replyProbe3. expectMessage ( " Hello-1 Charlie! " )
216-
217- // Take down the leader
218- // first.cluster.down(node: first.cluster.node.node) // FIXME: must also work when the node downs itself and shuts down (!!!) (we do not move to down currently, no default downing impl)
219- second. cluster. down ( node: first. cluster. node. node)
220-
221- // Ensure the node is seen down
222- try self . ensureNodes ( . down, on: second, systems: first)
223- try self . ensureNodes ( . down, on: third, systems: first)
224-
225- // At the same time, since the node was downed, it is not the leader anymore
226- try self . testKit ( third) . eventually ( within: . seconds( 10 ) ) {
227- try self . assertLeaderNode ( on: third, is: nil )
228- try self . assertLeaderNode ( on: second, is: nil )
229- }
230-
231- // `fourth` will become the new leader and singleton
232- try self . joinNodes ( node: fourth, with: second)
233- try self . ensureNodes ( . up, within: . seconds( 10 ) , systems: fourth, second, third)
234-
235- try self . testKit ( first) . eventually ( within: . seconds( 10 ) ) {
236- // The stashed messages get routed to new singleton running on `fourth`
237-
238- ref2. tell ( . greet( name: " Charlie-2 " , _replyTo: replyProbe2. ref) )
239- guard let reply2 = try replyProbe2. maybeExpectMessage ( ) else {
240- pprint ( " lost msg @ node 2 " )
241- throw TestError ( " No reply to \( replyProbe2) yet, singleton still rebalancing...? " )
242- }
243- reply2. shouldEqual ( " Hello-4 Charlie-2! " )
244-
245- ref3. tell ( . greet( name: " Charlie-3 " , _replyTo: replyProbe3. ref) )
246- guard let reply3 = try replyProbe3. maybeExpectMessage ( ) else {
247- pprint ( " lost msg @ node 3 " )
248- throw TestError ( " No reply to \( replyProbe3) yet, singleton still rebalancing...? " )
249- }
250- reply3. shouldEqual ( " Hello-4 Charlie-3! " )
251- }
252- }
253- }
254- }
255-
256- // ==== ----------------------------------------------------------------------------------------------------------------
257- // MARK: Test utilities
258-
259- struct GreeterSingleton : Actorable {
260- static let name = " greeter "
261-
262- private let greeting : String
263-
264- init ( _ greeting: String ) {
265- self . greeting = greeting
266- }
267-
268- func greet( name: String ) -> String {
269- " \( self . greeting) \( name) ! "
270- }
27148}
0 commit comments