Skip to content

Commit fbaeab9

Browse files
committed
Store a reference to the engine in receiver objects
This is a hack to ensure that the lifetime of the engine is tied to the lifetime of the receiver. This is necessary because the engine is a task that runs forever, and in cases where higher order built for example with the below idiom, the user would hold no references to the engine and it could get garbage collected before the receiver. formula = (grid_power_engine + bat_power_engine).build().new_receiver() Signed-off-by: Sahas Subramanian <[email protected]>
1 parent 04de58a commit fbaeab9

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

src/frequenz/sdk/timeseries/_formula_engine/_formula_engine.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,19 @@ def new_receiver(
360360
if self._task is None:
361361
self._task = asyncio.create_task(self._run())
362362

363-
return self._channel.new_receiver(name, max_size)
363+
recv = self._channel.new_receiver(name, max_size)
364+
365+
# This is a hack to ensure that the lifetime of the engine is tied to the
366+
# lifetime of the receiver. This is necessary because the engine is a task that
367+
# runs forever, and in cases where higher order built for example with the below
368+
# idiom, the user would hold no references to the engine and it could get
369+
# garbage collected before the receiver. This behaviour is explained in the
370+
# `asyncio.create_task` docs here:
371+
# https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task
372+
#
373+
# formula = (grid_power_engine + bat_power_engine).build().new_receiver()
374+
recv._engine_reference = self # type: ignore # pylint: disable=protected-access
375+
return recv
364376

365377

366378
class FormulaEngine3Phase(

0 commit comments

Comments
 (0)