35
35
logger = logging .getLogger (__name__ )
36
36
37
37
38
+ class StopIterSentinel :
39
+ """A sentinel class used to indicate that iteration should stop."""
40
+
41
+ pass
42
+
43
+
38
44
class KeyValue :
39
45
"""
40
46
KeyValue uses the JetStream KeyValue functionality.
@@ -278,6 +284,9 @@ async def purge_deletes(self, olderthan: int = 30 * 60) -> bool:
278
284
watcher = await self .watchall ()
279
285
delete_markers = []
280
286
async for update in watcher :
287
+ if update is None :
288
+ break
289
+
281
290
if update .operation == KV_DEL or update .operation == KV_PURGE :
282
291
delete_markers .append (update )
283
292
@@ -300,11 +309,11 @@ async def status(self) -> BucketStatus:
300
309
return KeyValue .BucketStatus (stream_info = info , bucket = self ._name )
301
310
302
311
class KeyWatcher :
312
+ STOP_ITER = StopIterSentinel ()
303
313
304
314
def __init__ (self , js ):
305
315
self ._js = js
306
- self ._updates : asyncio .Queue [KeyValue .Entry
307
- | None ] = asyncio .Queue (maxsize = 256 )
316
+ self ._updates : asyncio .Queue [KeyValue .Entry | None | StopIterSentinel ] = asyncio .Queue (maxsize = 256 )
308
317
self ._sub = None
309
318
self ._pending : Optional [int ] = None
310
319
@@ -317,6 +326,7 @@ async def stop(self):
317
326
stop will stop this watcher.
318
327
"""
319
328
await self ._sub .unsubscribe ()
329
+ await self ._updates .put (KeyValue .KeyWatcher .STOP_ITER )
320
330
321
331
async def updates (self , timeout = 5.0 ):
322
332
"""
@@ -331,10 +341,10 @@ def __aiter__(self):
331
341
return self
332
342
333
343
async def __anext__ (self ):
334
- entry = await self . _updates . get ()
335
- if not entry :
336
- raise StopAsyncIteration
337
- else :
344
+ while True :
345
+ entry = await self . _updates . get ()
346
+ if isinstance ( entry , StopIterSentinel ):
347
+ raise StopAsyncIteration
338
348
return entry
339
349
340
350
async def watchall (self , ** kwargs ) -> KeyWatcher :
0 commit comments