Skip to content

Commit d5a391f

Browse files
committed
Add method to re-send dispatch states after startup
Signed-off-by: Mathias L. Baumann <[email protected]>
1 parent cc85eb3 commit d5a391f

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

src/frequenz/dispatch/_dispatcher.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,17 @@ async def start(self) -> None:
210210
"""Start the actor."""
211211
self._actor.start()
212212

213+
async def resend_current_running_states(self, dispatch_type: str) -> None:
214+
"""Resend the current running states of all dispatches of a given type.
215+
216+
Warning: Usually you don't need to call this method. It is only useful
217+
when you need to recover the current running state of your actor.
218+
219+
Args:
220+
dispatch_type: The type of dispatches to resend.
221+
"""
222+
await self._actor.resend_current_running_states(dispatch_type)
223+
213224
@property
214225
def client(self) -> Client:
215226
"""Return the client."""

src/frequenz/dispatch/actor.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,23 @@ def __init__(
8484
always at index 0.
8585
"""
8686

87+
async def resend_current_running_states(self, dispatch_type: str) -> None:
88+
"""Trigger a resend of all running states.
89+
90+
Causes the current state to be sent out again on the running state
91+
change channel.
92+
93+
Args:
94+
dispatch_type: The type of dispatches to resend.
95+
"""
96+
_logger.info(
97+
"Resending current running states for dispatch type %s", dispatch_type
98+
)
99+
for dispatch in self._dispatches.values():
100+
if dispatch.type == dispatch_type:
101+
_logger.debug("Resending dispatch %s", dispatch)
102+
await self._send_running_state_change(dispatch)
103+
87104
async def _run(self) -> None:
88105
"""Run the actor."""
89106
_logger.info("Starting dispatch actor for microgrid %s", self._microgrid_id)

tests/test_frequenz_dispatch.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,3 +482,48 @@ async def test_notification_on_actor_start(
482482
# Expect notification of the running dispatch being ready to run
483483
ready_dispatch = await actor_env.running_state_change.receive()
484484
assert ready_dispatch.started
485+
486+
487+
async def test_notification_on_resend(
488+
actor_env: ActorTestEnv,
489+
generator: DispatchGenerator,
490+
) -> None:
491+
"""Test that the correct notifications are sent when resending dispatches."""
492+
# Generate a dispatch that is already running
493+
running_dispatch = generator.generate_dispatch()
494+
running_dispatch = replace(
495+
running_dispatch,
496+
active=True,
497+
duration=timedelta(seconds=10),
498+
start_time=_now() - timedelta(seconds=5),
499+
recurrence=RecurrenceRule(),
500+
type="I_SHOULD_RUN",
501+
)
502+
# Generate a dispatch that is not running
503+
stopped_dispatch = generator.generate_dispatch()
504+
stopped_dispatch = replace(
505+
stopped_dispatch,
506+
active=False,
507+
duration=timedelta(seconds=5),
508+
start_time=_now() - timedelta(seconds=5),
509+
recurrence=RecurrenceRule(),
510+
type="I_SHOULD_NOT_RUN",
511+
)
512+
await actor_env.actor.stop()
513+
514+
# Create the dispatches
515+
actor_env.client.set_dispatches(
516+
actor_env.microgrid_id, [running_dispatch, stopped_dispatch]
517+
)
518+
519+
# Start the actor
520+
actor_env.actor.start()
521+
# Resend the stopped dispatch, but expect no notification
522+
await actor_env.actor.resend_current_running_states(stopped_dispatch.type)
523+
# Resend the running dispatch
524+
await actor_env.actor.resend_current_running_states(running_dispatch.type)
525+
526+
# Expect notification of the running dispatch being ready to run
527+
ready_dispatch = await actor_env.running_state_change.receive()
528+
assert ready_dispatch.started
529+
assert ready_dispatch.type == running_dispatch.type

0 commit comments

Comments
 (0)