@@ -156,6 +156,7 @@ def test_should_get_table_from_router(self):
156156 assert table .readers == {("127.0.0.1" , 9004 ), ("127.0.0.1" , 9005 )}
157157 assert table .writers == {("127.0.0.1" , 9006 )}
158158 assert table .ttl == 300
159+ assert not pool .missing_writer
159160
160161 def test_null_info_should_return_null_table (self ):
161162 address = ("127.0.0.1" , 9001 )
@@ -177,12 +178,17 @@ def test_no_readers_should_raise_protocol_error(self):
177178 with self .assertRaises (ProtocolError ):
178179 _ = pool .fetch_routing_table (address )
179180
180- def test_no_writers_should_return_null_table (self ):
181+ def test_no_writers_should_return_table_with_no_writer (self ):
181182 with StubCluster ({9001 : "router_no_writers.script" }):
182183 address = ("127.0.0.1" , 9001 )
183184 with RoutingPool () as pool :
184185 table = pool .fetch_routing_table (address )
185- assert table is None
186+ assert table .routers == {("127.0.0.1" , 9001 ), ("127.0.0.1" , 9002 ),
187+ ("127.0.0.1" , 9003 )}
188+ assert table .readers == {("127.0.0.1" , 9004 ), ("127.0.0.1" , 9005 )}
189+ assert not table .writers
190+ assert table .ttl == 300
191+ assert pool .missing_writer
186192
187193
188194class RoutingConnectionPoolUpdateRoutingTableTestCase (StubTestCase ):
@@ -211,6 +217,20 @@ def test_roll_back_to_initial_server_if_failed_update_with_existing_routers(self
211217 assert table .writers == {("127.0.0.1" , 9006 )}
212218 assert table .ttl == 300
213219
220+ def test_try_initial_server_first_if_missing_writer (self ):
221+ with StubCluster ({9001 : "router.script" }):
222+ initial_address = ("127.0.0.1" , 9001 )
223+ with RoutingConnectionPool (connector , initial_address , {}) as pool :
224+ pool .missing_writer = True
225+ pool .update_routing_table ()
226+ table = pool .routing_table
227+ assert table .routers == {("127.0.0.1" , 9001 ), ("127.0.0.1" , 9002 ),
228+ ("127.0.0.1" , 9003 )}
229+ assert table .readers == {("127.0.0.1" , 9004 ), ("127.0.0.1" , 9005 )}
230+ assert table .writers == {("127.0.0.1" , 9006 )}
231+ assert table .ttl == 300
232+ assert not pool .missing_writer
233+
214234 def test_update_with_no_routers_should_signal_service_unavailable (self ):
215235 with RoutingPool () as pool :
216236 with self .assertRaises (ServiceUnavailable ):
@@ -226,7 +246,7 @@ def _test_server_outcome(self, server_outcomes, overall_outcome):
226246 routers = []
227247 for port , outcome in enumerate (server_outcomes , 9001 ):
228248 if outcome is None :
229- servers [port ] = "router_no_writers .script"
249+ servers [port ] = "rude_router .script"
230250 elif outcome is RoutingTable :
231251 servers [port ] = "router.script"
232252 elif outcome is ServiceUnavailable :
@@ -251,26 +271,37 @@ def _test_server_outcome(self, server_outcomes, overall_outcome):
251271 assert False , "Unexpected overall outcome %r" % overall_outcome
252272
253273
254- class RoutingConnectionPoolRefreshRoutingTableTestCase (StubTestCase ):
274+ class RoutingConnectionPoolEnsureRoutingTableTestCase (StubTestCase ):
255275 def test_should_update_if_stale (self ):
256276 with StubCluster ({9001 : "router.script" }):
257277 address = ("127.0.0.1" , 9001 )
258278 with RoutingPool (address ) as pool :
259279 first_updated_time = pool .routing_table .last_updated_time
260280 pool .routing_table .ttl = 0
261- pool .refresh_routing_table ( )
281+ pool .ensure_routing_table ( WRITE_ACCESS )
262282 second_updated_time = pool .routing_table .last_updated_time
263283 assert second_updated_time != first_updated_time
284+ assert not pool .missing_writer
264285
265286 def test_should_not_update_if_fresh (self ):
266287 with StubCluster ({9001 : "router.script" }):
267288 address = ("127.0.0.1" , 9001 )
268289 with RoutingPool (address ) as pool :
269- pool .refresh_routing_table ( )
290+ pool .ensure_routing_table ( WRITE_ACCESS )
270291 first_updated_time = pool .routing_table .last_updated_time
271- pool .refresh_routing_table ( )
292+ pool .ensure_routing_table ( WRITE_ACCESS )
272293 second_updated_time = pool .routing_table .last_updated_time
273294 assert second_updated_time == first_updated_time
295+ assert not pool .missing_writer
296+
297+ def test_should_flag_reading_without_writer (self ):
298+ with StubCluster ({9001 : "router_no_writers.script" }):
299+ address = ("127.0.0.1" , 9001 )
300+ with RoutingPool (address ) as pool :
301+ assert not pool .routing_table .is_fresh (READ_ACCESS )
302+ assert not pool .routing_table .is_fresh (WRITE_ACCESS )
303+ pool .ensure_routing_table (READ_ACCESS )
304+ assert pool .missing_writer
274305
275306 # TODO: fix flaky test
276307 # def test_concurrent_refreshes_should_not_block_if_fresh(self):
@@ -372,65 +403,90 @@ def test_should_refresh(self):
372403 with StubCluster ({9001 : "router.script" , 9004 : "empty.script" }):
373404 address = ("127.0.0.1" , 9001 )
374405 with RoutingPool (address ) as pool :
375- assert not pool .routing_table .is_fresh ()
406+ assert not pool .routing_table .is_fresh (READ_ACCESS )
376407 _ = pool .acquire (access_mode = READ_ACCESS )
377- assert pool .routing_table .is_fresh ()
408+ assert pool .routing_table .is_fresh (READ_ACCESS )
409+ assert not pool .missing_writer
378410
379411 def test_connected_to_reader (self ):
380412 with StubCluster ({9001 : "router.script" , 9004 : "empty.script" }):
381413 address = ("127.0.0.1" , 9001 )
382414 with RoutingPool (address ) as pool :
383- assert not pool .routing_table .is_fresh ()
415+ assert not pool .routing_table .is_fresh (READ_ACCESS )
384416 connection = pool .acquire (access_mode = READ_ACCESS )
385417 assert connection .server .address in pool .routing_table .readers
418+ assert not pool .missing_writer
386419
387420 def test_should_retry_if_first_reader_fails (self ):
388421 with StubCluster ({9001 : "router.script" ,
389422 9004 : "fail_on_init.script" ,
390423 9005 : "empty.script" }):
391424 address = ("127.0.0.1" , 9001 )
392425 with RoutingPool (address ) as pool :
393- assert not pool .routing_table .is_fresh ()
426+ assert not pool .routing_table .is_fresh (READ_ACCESS )
394427 _ = pool .acquire (access_mode = READ_ACCESS )
395428 assert ("127.0.0.1" , 9004 ) not in pool .routing_table .readers
396429 assert ("127.0.0.1" , 9005 ) in pool .routing_table .readers
397430
431+ def test_should_connect_to_read_in_absent_of_writer (self ):
432+ with StubCluster ({9001 : "router_no_writers.script" , 9004 : "empty.script" }):
433+ address = ("127.0.0.1" , 9001 )
434+ with RoutingPool (address ) as pool :
435+ assert not pool .routing_table .is_fresh (READ_ACCESS )
436+ connection = pool .acquire (access_mode = READ_ACCESS )
437+ assert connection .server .address in pool .routing_table .readers
438+ assert not pool .routing_table .is_fresh (WRITE_ACCESS )
439+ assert pool .missing_writer
440+
398441
399442class RoutingConnectionPoolAcquireForWriteTestCase (StubTestCase ):
400443 def test_should_refresh (self ):
401444 with StubCluster ({9001 : "router.script" , 9006 : "empty.script" }):
402445 address = ("127.0.0.1" , 9001 )
403446 with RoutingPool (address ) as pool :
404- assert not pool .routing_table .is_fresh ()
447+ assert not pool .routing_table .is_fresh (WRITE_ACCESS )
405448 _ = pool .acquire (access_mode = WRITE_ACCESS )
406- assert pool .routing_table .is_fresh ()
449+ assert pool .routing_table .is_fresh (WRITE_ACCESS )
450+ assert not pool .missing_writer
407451
408452 def test_connected_to_writer (self ):
409453 with StubCluster ({9001 : "router.script" , 9006 : "empty.script" }):
410454 address = ("127.0.0.1" , 9001 )
411455 with RoutingPool (address ) as pool :
412- assert not pool .routing_table .is_fresh ()
456+ assert not pool .routing_table .is_fresh (WRITE_ACCESS )
413457 connection = pool .acquire (access_mode = WRITE_ACCESS )
414458 assert connection .server .address in pool .routing_table .writers
459+ assert not pool .missing_writer
415460
416461 def test_should_retry_if_first_writer_fails (self ):
417462 with StubCluster ({9001 : "router_with_multiple_writers.script" ,
418463 9006 : "fail_on_init.script" ,
419464 9007 : "empty.script" }):
420465 address = ("127.0.0.1" , 9001 )
421466 with RoutingPool (address ) as pool :
422- assert not pool .routing_table .is_fresh ()
467+ assert not pool .routing_table .is_fresh (WRITE_ACCESS )
423468 _ = pool .acquire (access_mode = WRITE_ACCESS )
424469 assert ("127.0.0.1" , 9006 ) not in pool .routing_table .writers
425470 assert ("127.0.0.1" , 9007 ) in pool .routing_table .writers
426471
472+ def test_should_error_to_writer_in_absent_of_reader (self ):
473+ with StubCluster ({9001 : "router_no_readers.script" }):
474+ address = ("127.0.0.1" , 9001 )
475+ with RoutingPool (address ) as pool :
476+ assert not pool .routing_table .is_fresh (WRITE_ACCESS )
477+ with self .assertRaises (ProtocolError ):
478+ _ = pool .acquire (access_mode = WRITE_ACCESS )
479+ assert not pool .routing_table .is_fresh (READ_ACCESS )
480+ assert not pool .routing_table .is_fresh (WRITE_ACCESS )
481+ assert not pool .missing_writer
482+
427483
428484class RoutingConnectionPoolRemoveTestCase (StubTestCase ):
429485 def test_should_remove_router_from_routing_table_if_present (self ):
430486 with StubCluster ({9001 : "router.script" }):
431487 address = ("127.0.0.1" , 9001 )
432488 with RoutingPool (address ) as pool :
433- pool .refresh_routing_table ( )
489+ pool .ensure_routing_table ( WRITE_ACCESS )
434490 target = ("127.0.0.1" , 9001 )
435491 assert target in pool .routing_table .routers
436492 pool .remove (target )
@@ -440,7 +496,7 @@ def test_should_remove_reader_from_routing_table_if_present(self):
440496 with StubCluster ({9001 : "router.script" }):
441497 address = ("127.0.0.1" , 9001 )
442498 with RoutingPool (address ) as pool :
443- pool .refresh_routing_table ( )
499+ pool .ensure_routing_table ( WRITE_ACCESS )
444500 target = ("127.0.0.1" , 9004 )
445501 assert target in pool .routing_table .readers
446502 pool .remove (target )
@@ -450,7 +506,7 @@ def test_should_remove_writer_from_routing_table_if_present(self):
450506 with StubCluster ({9001 : "router.script" }):
451507 address = ("127.0.0.1" , 9001 )
452508 with RoutingPool (address ) as pool :
453- pool .refresh_routing_table ( )
509+ pool .ensure_routing_table ( WRITE_ACCESS )
454510 target = ("127.0.0.1" , 9006 )
455511 assert target in pool .routing_table .writers
456512 pool .remove (target )
@@ -460,6 +516,6 @@ def test_should_not_fail_if_absent(self):
460516 with StubCluster ({9001 : "router.script" }):
461517 address = ("127.0.0.1" , 9001 )
462518 with RoutingPool (address ) as pool :
463- pool .refresh_routing_table ( )
519+ pool .ensure_routing_table ( WRITE_ACCESS )
464520 target = ("127.0.0.1" , 9007 )
465521 pool .remove (target )
0 commit comments