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.
@@ -275,6 +281,9 @@ async def purge_deletes(self, olderthan: int = 30 * 60) -> bool:
275
281
watcher = await self .watchall ()
276
282
delete_markers = []
277
283
async for update in watcher :
284
+ if update is None :
285
+ break
286
+
278
287
if update .operation == KV_DEL or update .operation == KV_PURGE :
279
288
delete_markers .append (update )
280
289
@@ -299,11 +308,11 @@ async def status(self) -> BucketStatus:
299
308
return KeyValue .BucketStatus (stream_info = info , bucket = self ._name )
300
309
301
310
class KeyWatcher :
311
+ STOP_ITER = StopIterSentinel ()
302
312
303
313
def __init__ (self , js ):
304
314
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 )
307
316
self ._sub = None
308
317
self ._pending : Optional [int ] = None
309
318
@@ -316,6 +325,7 @@ async def stop(self):
316
325
stop will stop this watcher.
317
326
"""
318
327
await self ._sub .unsubscribe ()
328
+ await self ._updates .put (KeyValue .KeyWatcher .STOP_ITER )
319
329
320
330
async def updates (self , timeout = 5.0 ):
321
331
"""
@@ -330,10 +340,10 @@ def __aiter__(self):
330
340
return self
331
341
332
342
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
337
347
return entry
338
348
339
349
async def watchall (self , ** kwargs ) -> KeyWatcher :
0 commit comments