Skip to content

Commit d5a66e0

Browse files
committed
WIP fix test_producer.py
1 parent e416dfe commit d5a66e0

File tree

3 files changed

+60
-23
lines changed

3 files changed

+60
-23
lines changed

src/frequenz/sdk/timeseries/formula_engine/_formula_generators/_producer_power_formula.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,16 @@ def generate( # noqa: DOC502
7979

8080
if self._config.allow_fallback:
8181
fallbacks = self._get_fallback_formulas(producer_components)
82+
print(
83+
f"ProducerPowerFormula: {dict({str(c): f for c, f in fallbacks.items()})}"
84+
)
8285

8386
for idx, (primary_component, fallback_formula) in enumerate(
8487
fallbacks.items()
8588
):
89+
print(f"\t{idx}: {primary_component=}")
90+
print(f"\t{is_not_meter(primary_component)=}")
91+
8692
if idx > 0:
8793
builder.push_oper("+")
8894

@@ -121,6 +127,9 @@ def _get_fallback_formulas(
121127
A dictionary mapping primary components to their FallbackFormulaMetricFetcher.
122128
"""
123129
fallbacks = self._get_metric_fallback_components(components)
130+
print(
131+
f"fallback components for {ProducerPowerFormula}: {dict({str(c): [str(cc) for cc in f] for c, f in fallbacks.items()})}"
132+
)
124133

125134
fallback_formulas: dict[
126135
Component, FallbackFormulaMetricFetcher[Power] | None

src/frequenz/sdk/timeseries/formula_engine/_formula_steps.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,9 +434,16 @@ async def _synchronize_and_fetch_fallback(
434434
fetcher or if the fallback fetcher fails to fetch the next value.
435435
"""
436436
# fallback_fetcher was not used, yet. We need to fetch first value.
437+
print(f"MetricFetcher<{self._name}>: {self._latest_fallback_sample=}")
437438
if self._latest_fallback_sample is None:
438439
try:
440+
print(
441+
f"MetricFetcher<{self._name}>: RECEIVING FROM FALLBACK {fallback_fetcher.name}"
442+
)
439443
self._latest_fallback_sample = await fallback_fetcher.receive()
444+
print(
445+
f"MetricFetcher<{self._name}>: RECEIVED {self._latest_fallback_sample=}"
446+
)
440447
except ReceiverError as err:
441448
_logger.error(
442449
"Fallback metric fetcher %s failed to fetch next value: %s."
@@ -447,6 +454,9 @@ async def _synchronize_and_fetch_fallback(
447454
return None
448455

449456
if primary_fetcher_sample.timestamp < self._latest_fallback_sample.timestamp:
457+
print(
458+
f"MetricFetcher<{self._name}>: {primary_fetcher_sample.timestamp=} < {self._latest_fallback_sample.timestamp=}"
459+
)
450460
return None
451461

452462
# Synchronize the fallback fetcher with primary one
@@ -510,15 +520,25 @@ async def fetch_next(self) -> Sample[QuantityT] | None:
510520
return self._next_value
511521

512522
async def _fetch_next(self) -> Sample[QuantityT] | None:
523+
print(f"MetricFetcher<{self._name}>: FETCHING NEXT")
513524
if self._fallback is None:
514-
return await self._stream.receive()
525+
print("\tNO FALLBACK")
526+
next_value = await self._stream.receive()
527+
print(f"\tFETCHED {next_value!r}")
528+
return next_value
515529

530+
print("\tWITH FALLBACK")
516531
if self._fallback.is_running:
517-
return await self.fetch_next_with_fallback(self._fallback)
532+
print("\tFALLBACK IS RUNNING")
533+
next_value = await self.fetch_next_with_fallback(self._fallback)
534+
print(f"\tFETCHED {next_value!r}")
535+
return next_value
518536

537+
print("\tFALLBACK NOT RUNNING")
519538
next_value = None
520539
try:
521540
next_value = await self._stream.receive()
541+
print(f"\tFETCHED {next_value!r}")
522542
except ReceiverError as err:
523543
_logger.error("Failed to fetch next value from %s: %s", self._name, err)
524544
else:

tests/timeseries/test_producer.py

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
"""Test the logical component for calculating high level producer metrics."""
55

6+
import asyncio
67
from contextlib import AsyncExitStack
78

89
from frequenz.quantities import Power
@@ -114,59 +115,66 @@ async def test_producer_fallback_formula(self, mocker: MockerFixture) -> None:
114115

115116
# fmt: off
116117
expected_input_output: list[
117-
tuple[list[float | None], list[float | None], list[float | None], Power | None]
118+
tuple[float, list[float | None], list[float | None], list[float | None], Power | None]
118119
] = [
119-
# ([pv_meter_power], [pv_inverter_power], [chp_power], expected_power)
120+
# (test number, [pv_meter_power], [pv_inverter_power], [chp_power], expected_power)
121+
# Case 1: All components are available
120122
# Add power from meters and chp
121-
([-1.0, -2.0], [None, -200.0], [300], Power.from_watts(297.0)),
122-
([-1.0, -10], [-100.0, -200.0], [400], Power.from_watts(389.0)),
123+
(1.1, [-1.0, -2.0], [None, -200.0], [300], Power.from_watts(297.0)),
124+
(1.2, [-1.0, -10], [-100.0, -200.0], [400], Power.from_watts(389.0)),
123125
# Case 2: The first meter is unavailable (None).
124126
# Subscribe to the fallback inverter, but return None as the result,
125127
# according to the "nones-are-zero" rule
126-
([None, -2.0], [-100, -200.0], [400], None),
128+
(2.1, [None, -2.0], [-100, -200.0], [400], None),
127129
# Case 3: First meter is unavailable (None). Fallback inverter provides
128130
# a value.
129131
# Add second meter, first inverter and chp power
130-
([None, -2.0], [-100, -200.0], [400], Power.from_watts(298.0)),
131-
([None, -2.0], [-50, -200.0], [300], Power.from_watts(248.0)),
132+
(3.1, [None, -2.0], [-100, -200.0], [400], Power.from_watts(298.0)),
133+
(3.2, [None, -2.0], [-50, -200.0], [300], Power.from_watts(248.0)),
132134
# Case 4: Both first meter and its fallback inverter are unavailable
133135
# (None). Return 0 from failing component according to the
134136
# "nones-are-zero" rule.
135-
([None, -2.0], [None, -200.0], [300], Power.from_watts(298.0)),
136-
([None, -10.0], [-20.0, -200.0], [300], Power.from_watts(270.0)),
137+
(4.1, [None, -2.0], [None, -200.0], [300], Power.from_watts(298.0)),
138+
(4.2, [None, -10.0], [-20.0, -200.0], [300], Power.from_watts(270.0)),
137139
# Case 5: CHP is unavailable. Return 0 from failing component
138140
# according to the "nones-are-zero" rule.
139-
([None, -10.0], [-20.0, -200.0], [None], Power.from_watts(-30.0)),
141+
(5.1, [None, -10.0], [-20.0, -200.0], [None], Power.from_watts(-30.0)),
140142
# Case 6: Both meters are unavailable (None). Subscribe for fallback inverter
141-
([None, None], [-20.0, -200.0], [None], None),
142-
([None, None], [-20.0, -200.0], [None], Power.from_watts(-220.0)),
143-
([None, None], [None, -200.0], [None], Power.from_watts(-200.0)),
143+
(6.1, [None, None], [-20.0, -200.0], [None], None),
144+
(6.2, [None, None], [-20.0, -200.0], [None], Power.from_watts(-220.0)),
145+
(6.3, [None, None], [None, -200.0], [None], Power.from_watts(-200.0)),
144146
# Case 7: All components are unavailable (None). Return 0 according to the
145147
# "nones-are-zero" rule.
146-
([None, None], [None, None], [None], Power.from_watts(0)),
147-
([None, None], [None, None], [None], Power.from_watts(0)),
148-
([None, None], [None, None], [300.0], Power.from_watts(300.0)),
149-
([-200.0, None], [None, -100.0], [50.0], Power.from_watts(-250.0)),
150-
([-200.0, -200.0], [-10.0, -20.0], [50.0], Power.from_watts(-350.0)),
148+
(7.1, [None, None], [None, None], [None], Power.from_watts(0)),
149+
(7.2, [None, None], [None, None], [None], Power.from_watts(0)),
150+
(7.3, [None, None], [None, None], [300.0], Power.from_watts(300.0)),
151+
(7.4, [-200.0, None], [None, -100.0], [50.0], Power.from_watts(-250.0)),
152+
(7.5, [-200.0, -200.0], [-10.0, -20.0], [50.0], Power.from_watts(-350.0)),
151153
# Case 8: Meter is unavailable but we already subscribed for inverter
152154
# So don't return None in this case. Just proper formula result.
153-
([None, -200.0], [-10.0, -100.0], [50.0], Power.from_watts(-160.0)),
155+
(8.1, [None, -200.0], [-10.0, -100.0], [50.0], Power.from_watts(-160.0)),
154156

155157
]
156158
# fmt: on
157159

158-
for idx, (
160+
for (
161+
idx,
159162
meter_power,
160163
pv_inverter_power,
161164
chp_power,
162165
expected_power,
163-
) in enumerate(expected_input_output):
166+
) in expected_input_output:
167+
print(
168+
f"\n----------------------------------------------------\nTEST CASE {idx}"
169+
)
164170
await mockgrid.mock_resampler.send_chp_power(chp_power)
165171
await mockgrid.mock_resampler.send_meter_power(meter_power)
166172
await mockgrid.mock_resampler.send_pv_inverter_power(pv_inverter_power)
167173
mockgrid.mock_resampler.next_ts()
174+
await asyncio.sleep(0.1)
168175

169176
result = await producer_power_receiver.receive()
177+
print(f">>>>> result: {result}")
170178
assert result.value == expected_power, (
171179
f"Test case {idx} failed:"
172180
+ f" meter_power: {meter_power}"

0 commit comments

Comments
 (0)