Skip to content

Simple SDK app does not recover after networking service restart #1036

@daniel-zullo-frequenz

Description

@daniel-zullo-frequenz

What happened?

The resampler is not able to get power metrics after restarting the networking service where a simple SDK application is running

__main__ INFO:Latest battery consumption: Sample(timestamp=datetime.datetime(2024, 8, 12, 12, 49, 57, tzinfo=datetime.timezone.utc), value=Power(value=0.0, exponent=0))
__main__ INFO:Latest net consumption: Sample(timestamp=datetime.datetime(2024, 8, 12, 12, 49, 57, tzinfo=datetime.timezone.utc), value=None)
frequenz.sdk.timeseries._resampling WARNING:No relevant samples found for: component_metric_request<namespace=grid-c01a4328-2e56-4017-b3df-594723abe827,component_id=1001,metric_id=ACTIVE_POWER,start=None>
frequenz.sdk.timeseries._resampling WARNING:No relevant samples found for: component_metric_request<namespace=battery-pool-frozenset({2009, 2003, 2006})-80a2a06b-34db-4545-8d92-01eeb4ef53da,component_id=2002,metric_id=ACTIVE_POWER,start=None>
frequenz.sdk.timeseries._resampling WARNING:No relevant samples found for: component_metric_request<namespace=battery-pool-frozenset({2009, 2003, 2006})-80a2a06b-34db-4545-8d92-01eeb4ef53da,component_id=2005,metric_id=ACTIVE_POWER,start=None>
frequenz.sdk.timeseries._resampling WARNING:No relevant samples found for: component_metric_request<namespace=battery-pool-frozenset({2009, 2003, 2006})-80a2a06b-34db-4545-8d92-01eeb4ef53da,component_id=2008,metric_id=ACTIVE_POWER,start=None>

Also pleae notice that a similar behaviour is observed when pausing the application with ctrl-z and resuming it after +20 minutes.

What did you expect instead?

The resampler recovers getting new power values after a networking service restart.

Affected version(s)

Observed in v0.25.2, v1.0.0-rc601 and higher versions

Affected part(s)

Core components (data structures, etc.) (part:core), Microgrid (API, component graph, etc.) (part:microgrid)

Extra information

Simple application to reproduce the issue:

# License: All rights reserved
# Copyright © 2024 Frequenz Energy-as-a-Service GmbH

"""Application to read net and battery pool power consumption data."""

import asyncio
import logging
import os
from datetime import timedelta

from frequenz.channels import Receiver, select, selected_from
from frequenz.sdk.actor import Actor
from frequenz.sdk import actor, microgrid
from frequenz.sdk.timeseries import Power, Sample
from frequenz.sdk.timeseries._resampling import ResamplerConfig


_logger = logging.getLogger(__name__)


class PowerReadingActor(Actor):
    """Actor to read net and battery pool power consumption data."""

    def __init__(
        self,
        recv_net_consumption: Receiver[Sample[Power]],
        recv_bat_consumption: Receiver[Sample[Power]],
    ):
        """Initialize the actor.

        Args:
            recv_net_consumption: Receiver channel for grid power consumption
                without battery pool power consumption data.
            recv_bat_consumption: Receiver channel for battery pool power
                consumption data.
        """
        super().__init__()
        self._recv_net_consumption = recv_net_consumption
        self._recv_bat_consumption = recv_bat_consumption

    async def _run(self) -> None:
        """Run the actor."""
        async for selected in select(
            self._recv_net_consumption,
            self._recv_bat_consumption,
        ):
            if selected_from(selected, self._recv_net_consumption):
                net_consumption_sample = selected.message
                if not net_consumption_sample:
                    raise ValueError("Net consumption data channel closed.")
                _logger.info("Latest net consumption: %s", net_consumption_sample)

            elif selected_from(selected, self._recv_bat_consumption):
                bat_consumption_sample = selected.message
                if not bat_consumption_sample:
                    raise ValueError("Battery pool consumption data channel closed.")
                _logger.info("Latest battery consumption: %s", bat_consumption_sample)


async def run() -> None:
    """Run the actor."""
    logging.basicConfig(
        level=logging.DEBUG, format="%(asctime)s %(name)s %(levelname)s:%(message)s"
    )

    microgrid_url = os.getenv(
        key="MICROGRID_API_URL", default="grpc://[2a01:4f8:c010:1adf::1]:62060"
    )

    await microgrid.initialize(
        server_url=microgrid_url,
        resampler_config=ResamplerConfig(
            resampling_period=timedelta(seconds=1.0),
        ),
    )

    grid = microgrid.grid()
    battery_pool = microgrid.new_battery_pool(priority=1)

    net_power_formula = (grid.power - battery_pool.power).build("net_power")

    power_reading_actor = PowerReadingActor(
        recv_net_consumption=net_power_formula.new_receiver(),
        recv_bat_consumption=battery_pool.power.new_receiver(),
    )

    await actor.run(power_reading_actor)


def main() -> None:
    """Run the application."""
    asyncio.run(run())


if __name__ == "__main__":
    main()

Commands to restart the networking service:

sudo nmcli networking off
sleep 5
sudo nmcli networking on

Metadata

Metadata

Labels

part:coreAffects the SDK core components (data structures, etc.)part:microgridAffects the interactions with the microgridpriority:URGENTAddress this immediately or the sky will falltype:bugSomething isn't working

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions