3535logger = logging .getLogger (__name__ )
3636
3737
38+ class StopIterSentinel :
39+ """A sentinel class used to indicate that iteration should stop."""
40+
41+ pass
42+
43+
3844class KeyValue :
3945 """
4046 KeyValue uses the JetStream KeyValue functionality.
@@ -275,6 +281,9 @@ async def purge_deletes(self, olderthan: int = 30 * 60) -> bool:
275281 watcher = await self .watchall ()
276282 delete_markers = []
277283 async for update in watcher :
284+ if update is None :
285+ break
286+
278287 if update .operation == KV_DEL or update .operation == KV_PURGE :
279288 delete_markers .append (update )
280289
@@ -299,11 +308,11 @@ async def status(self) -> BucketStatus:
299308 return KeyValue .BucketStatus (stream_info = info , bucket = self ._name )
300309
301310 class KeyWatcher :
311+ STOP_ITER = StopIterSentinel ()
302312
303313 def __init__ (self , js ):
304314 self ._js = js
305- self ._updates : asyncio .Queue [KeyValue .Entry
306- | None ] = asyncio .Queue (maxsize = 256 )
315+ self ._updates : asyncio .Queue [KeyValue .Entry | None | StopIterSentinel ] = asyncio .Queue (maxsize = 256 )
307316 self ._sub = None
308317 self ._pending : Optional [int ] = None
309318
@@ -316,6 +325,7 @@ async def stop(self):
316325 stop will stop this watcher.
317326 """
318327 await self ._sub .unsubscribe ()
328+ await self ._updates .put (KeyValue .KeyWatcher .STOP_ITER )
319329
320330 async def updates (self , timeout = 5.0 ):
321331 """
@@ -330,10 +340,10 @@ def __aiter__(self):
330340 return self
331341
332342 async def __anext__ (self ):
333- entry = await self . _updates . get ()
334- if not entry :
335- raise StopAsyncIteration
336- else :
343+ while True :
344+ entry = await self . _updates . get ()
345+ if isinstance ( entry , StopIterSentinel ):
346+ raise StopAsyncIteration
337347 return entry
338348
339349 async def watchall (self , ** kwargs ) -> KeyWatcher :
0 commit comments