@@ -366,8 +366,7 @@ async def _fetch(self, timer: Timer) -> None:
366
366
"""
367
367
self ._initial_fetch_event .clear ()
368
368
369
- old_dispatches = self ._dispatches
370
- self ._dispatches = {}
369
+ new_dispatches = {}
371
370
372
371
try :
373
372
_logger .debug ("Fetching dispatches for microgrid %s" , self ._microgrid_id )
@@ -381,9 +380,9 @@ async def _fetch(self, timer: Timer) -> None:
381
380
continue
382
381
dispatch = Dispatch (client_dispatch )
383
382
384
- self . _dispatches [dispatch .id ] = dispatch
385
- old_dispatch = old_dispatches . pop (dispatch .id , None )
386
- if not old_dispatch :
383
+ new_dispatches [dispatch .id ] = dispatch
384
+ old_dispatch = self . _dispatches . get (dispatch .id , None )
385
+ if old_dispatch is None :
387
386
_logger .debug ("New dispatch: %s" , dispatch )
388
387
await self ._update_dispatch_schedule_and_notify (
389
388
dispatch , None , timer
@@ -396,23 +395,37 @@ async def _fetch(self, timer: Timer) -> None:
396
395
)
397
396
await self ._lifecycle_events_tx .send (Updated (dispatch = dispatch ))
398
397
399
- _logger .debug ("Received %s dispatches" , len (self . _dispatches ))
398
+ _logger .debug ("Received %s dispatches" , len (new_dispatches ))
400
399
401
400
except grpc .aio .AioRpcError as error :
402
401
_logger .error ("Error fetching dispatches: %s" , error )
403
- self ._dispatches = old_dispatches
404
402
return
405
403
406
- for dispatch in old_dispatches .values ():
404
+ # We make a copy because we mutate self._dispatch.keys() inside the loop
405
+ for dispatch_id in frozenset (self ._dispatches .keys () - new_dispatches .keys ()):
406
+ try :
407
+ dispatch = self ._dispatches .pop (dispatch_id )
408
+ except KeyError as error :
409
+ _logger .warning (
410
+ "Inconsistency in cache detected. "
411
+ + "Tried to delete non-existing dispatch %s (%s)" ,
412
+ dispatch_id ,
413
+ error ,
414
+ )
415
+ continue
416
+
407
417
_logger .debug ("Deleted dispatch: %s" , dispatch )
408
- await self ._lifecycle_events_tx .send (Deleted (dispatch = dispatch ))
409
418
await self ._update_dispatch_schedule_and_notify (None , dispatch , timer )
410
419
411
420
# Set deleted only here as it influences the result of dispatch.started
412
- # which is used in above in _running_state_change
421
+ # which is used in the func call above ^
413
422
dispatch ._set_deleted () # pylint: disable=protected-access
414
423
await self ._lifecycle_events_tx .send (Deleted (dispatch = dispatch ))
415
424
425
+ # Update the dispatch list with the dispatches
426
+ self ._dispatches .update (new_dispatches )
427
+
428
+ # Set event to indicate fetch ran at least once
416
429
self ._initial_fetch_event .set ()
417
430
418
431
async def _update_dispatch_schedule_and_notify (
0 commit comments