Skip to content

Commit f2e67ba

Browse files
committed
Add a drop_old_proposals method in PowerManager algorithms
In the matryoshka algorithm, this method is implemented to delete proposals that haven't been replaced/updated in the last `max_proposal_age`. Signed-off-by: Sahas Subramanian <[email protected]>
1 parent 370db17 commit f2e67ba

File tree

4 files changed

+36
-4
lines changed

4 files changed

+36
-4
lines changed

src/frequenz/sdk/actor/_power_managing/_base_classes.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,3 +285,13 @@ def get_status(
285285
Returns:
286286
The bounds for the components.
287287
"""
288+
289+
@abc.abstractmethod
290+
def drop_old_proposals(self, loop_time: float) -> None:
291+
"""Drop old proposals.
292+
293+
This method is called periodically by the power manager.
294+
295+
Args:
296+
loop_time: The current loop time.
297+
"""

src/frequenz/sdk/actor/_power_managing/_matryoshka.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import logging
2323
import typing
24+
from datetime import timedelta
2425

2526
from typing_extensions import override
2627

@@ -40,8 +41,9 @@
4041
class Matryoshka(BaseAlgorithm):
4142
"""The matryoshka algorithm."""
4243

43-
def __init__(self) -> None:
44+
def __init__(self, max_proposal_age: timedelta) -> None:
4445
"""Create a new instance of the matryoshka algorithm."""
46+
self._max_proposal_age_sec = max_proposal_age.total_seconds()
4547
self._component_buckets: dict[frozenset[int], SortedSet[Proposal]] = {}
4648
self._target_power: dict[frozenset[int], Power] = {}
4749

@@ -267,3 +269,21 @@ def get_status(
267269
_exclusion_bounds=system_bounds.exclusion_bounds,
268270
distribution_result=distribution_result,
269271
)
272+
273+
@override
274+
def drop_old_proposals(self, loop_time: float) -> None:
275+
"""Drop old proposals.
276+
277+
This will remove all proposals that have not been updated for longer than
278+
`max_proposal_age`.
279+
280+
Args:
281+
loop_time: The current loop time.
282+
"""
283+
for bucket in self._component_buckets.values():
284+
to_delete = []
285+
for proposal in bucket:
286+
if (loop_time - proposal.creation_time) > self._max_proposal_age_sec:
287+
to_delete.append(proposal)
288+
for proposal in to_delete:
289+
bucket.delete(proposal)

src/frequenz/sdk/actor/_power_managing/_power_managing_actor.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ def __init__( # pylint: disable=too-many-arguments
7575
self._subscriptions: dict[frozenset[int], dict[int, Sender[_Report]]] = {}
7676
self._distribution_results: dict[frozenset[int], power_distributing.Result] = {}
7777

78-
self._algorithm: BaseAlgorithm = Matryoshka()
78+
self._algorithm: BaseAlgorithm = Matryoshka(
79+
max_proposal_age=timedelta(seconds=60.0)
80+
)
7981

8082
super().__init__()
8183

tests/actor/_power_managing/test_matryoshka.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"""Tests for the Matryoshka power manager algorithm."""
55

66
import asyncio
7-
from datetime import datetime, timezone
7+
from datetime import datetime, timedelta, timezone
88

99
from frequenz.sdk import timeseries
1010
from frequenz.sdk.actor._power_managing import Proposal
@@ -23,7 +23,7 @@ def __init__(
2323
"""Create a new instance of the stateful tester."""
2424
self._call_count = 0
2525
self._batteries = batteries
26-
self._algorithm = Matryoshka()
26+
self._algorithm = Matryoshka(max_proposal_age=timedelta(seconds=60.0))
2727
self._system_bounds = system_bounds
2828

2929
def tgt_power( # pylint: disable=too-many-arguments

0 commit comments

Comments
 (0)