@@ -970,29 +970,33 @@ async def get_all_documents(
970970 assert isinstance (resp , dict )
971971 return AllDocumentsResponse (cast (dict , resp ))
972972
973+ @tenacity .retry (
974+ wait = tenacity .wait_random_exponential (multiplier = 1 , max = 10 ),
975+ # SGW import/propagation polling is ~10s, so allow 60s for it plus work.
976+ stop = tenacity .stop_after_delay (60 ),
977+ reraise = True ,
978+ retry = tenacity .retry_if_exception_type (AssertionError ),
979+ )
973980 async def wait_for_all_documents (
974981 self ,
975982 db_name : str ,
976983 min_count : int ,
977984 scope : str = "_default" ,
978985 collection : str = "_default" ,
979- max_retries : int = 30 ,
980- retry_delay : int = 1 ,
981986 ) -> AllDocumentsResponse :
982987 """
983- Poll _all_docs until at least min_count docs are present, or time out.
988+ Retry _all_docs until at least min_count docs are present, then return the
989+ response. Raises AssertionError if the count is not reached within 60s.
984990
985991 Docs that arrive via an asynchronous path (SDK import, re-import after an
986992 SGW restart, cross-node/ISGR propagation) are not guaranteed to be visible
987- in a single read. Returns the last response either way so the caller can
988- assert and report how far it got.
993+ in a single read.
989994 """
990995 all_docs = await self .get_all_documents (db_name , scope , collection )
991- for _ in range (max_retries ):
992- if len (all_docs .rows ) >= min_count :
993- break
994- await asyncio .sleep (retry_delay )
995- all_docs = await self .get_all_documents (db_name , scope , collection )
996+ assert len (all_docs .rows ) >= min_count , (
997+ f"Expected at least { min_count } docs in "
998+ f"{ db_name } .{ scope } .{ collection } , got { len (all_docs .rows )} "
999+ )
9961000 return all_docs
9971001
9981002 async def get_changes (
@@ -2074,32 +2078,31 @@ async def wait_for_db_up(
20742078 # Wait for the node to settle down after coming online
20752079 await asyncio .sleep (settle_online )
20762080
2077- async def wait_for_import_count (
2078- self ,
2079- db_name : str ,
2080- min_count : int ,
2081- max_retries : int = 30 ,
2082- retry_delay : int = 1 ,
2083- ) -> int :
2081+ @tenacity .retry (
2082+ wait = tenacity .wait_random_exponential (multiplier = 1 , max = 10 ),
2083+ # SGW import polling is ~10s, so allow 60s for it plus work.
2084+ stop = tenacity .stop_after_delay (60 ),
2085+ reraise = True ,
2086+ retry = tenacity .retry_if_exception_type (AssertionError ),
2087+ )
2088+ async def wait_for_import_count (self , db_name : str , min_count : int ) -> int :
20842089 """
2085- Poll the shared_bucket_import expvar until import_count >= min_count, or
2086- time out. Returns the last observed count so the caller can assert on it .
2090+ Retry the shared_bucket_import expvar until import_count >= min_count, then
2091+ return it. Raises AssertionError if not reached within 60s .
20872092 """
2088- import_count = 0
2089- for _ in range (max_retries ):
2090- resp_data = await self ._send_request ("get" , "/_expvar" )
2091- assert isinstance (resp_data , dict )
2092- expvars = cast (dict , resp_data )
2093- import_count = (
2094- expvars .get ("syncgateway" , {})
2095- .get ("per_db" , {})
2096- .get (db_name , {})
2097- .get ("shared_bucket_import" , {})
2098- .get ("import_count" , 0 )
2099- )
2100- if import_count >= min_count :
2101- break
2102- await asyncio .sleep (retry_delay )
2093+ resp_data = await self ._send_request ("get" , "/_expvar" )
2094+ assert isinstance (resp_data , dict )
2095+ expvars = cast (dict , resp_data )
2096+ import_count = (
2097+ expvars .get ("syncgateway" , {})
2098+ .get ("per_db" , {})
2099+ .get (db_name , {})
2100+ .get ("shared_bucket_import" , {})
2101+ .get ("import_count" , 0 )
2102+ )
2103+ assert import_count >= min_count , (
2104+ f"Expected import_count >= { min_count } for { db_name } , got { import_count } "
2105+ )
21032106 return import_count
21042107
21052108 async def create_user_client (
0 commit comments