44"""A post-fix formula evaluator that operates on `Sample` receivers."""
55
66import asyncio
7- from collections .abc import Callable
7+ from collections .abc import Callable , Awaitable
88from datetime import datetime
99from math import isinf , isnan
10- from typing import Generic
10+ from typing import Generic , Any
1111
1212from .._base_types import QuantityT , Sample
1313from ._formula_steps import FormulaStep , MetricFetcher
14+ from frequenz .sdk ._internal ._asyncio import cancel_and_await
1415
1516
1617class FormulaEvaluator (Generic [QuantityT ]):
@@ -38,6 +39,7 @@ def __init__(
3839 self ._metric_fetchers : dict [str , MetricFetcher [QuantityT ]] = metric_fetchers
3940 self ._first_run = True
4041 self ._create_method : Callable [[float ], QuantityT ] = create_method
42+ self ._pending_fetch_tasks : list [asyncio .Task [Any ]] = []
4143
4244 async def _synchronize_metric_timestamps (
4345 self , metrics : set [asyncio .Task [Sample [QuantityT ] | None ]]
@@ -87,6 +89,14 @@ async def _synchronize_metric_timestamps(
8789 self ._first_run = False
8890 return latest_ts
8991
92+ async def stop (self ) -> None :
93+ tasks_to_cancel = [
94+ asyncio .create_task (cancel_and_await (task ))
95+ for task in self ._pending_fetch_tasks
96+ ]
97+ await asyncio .wait (tasks_to_cancel , return_when = asyncio .ALL_COMPLETED )
98+ self ._pending_fetch_tasks = []
99+
90100 async def apply (self ) -> Sample [QuantityT ]:
91101 """Fetch the latest metrics, apply the formula once and return the result.
92102
@@ -98,11 +108,13 @@ async def apply(self) -> Sample[QuantityT]:
98108 failed.
99109 """
100110 eval_stack : list [float ] = []
111+ self ._pending_fetch_tasks = [
112+ asyncio .create_task (fetcher .fetch_next (), name = name )
113+ for name , fetcher in self ._metric_fetchers .items ()
114+ ]
115+
101116 ready_metrics , pending = await asyncio .wait (
102- [
103- asyncio .create_task (fetcher .fetch_next (), name = name )
104- for name , fetcher in self ._metric_fetchers .items ()
105- ],
117+ self ._pending_fetch_tasks ,
106118 return_when = asyncio .ALL_COMPLETED ,
107119 )
108120
0 commit comments