Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

## New Features

<!-- Here goes the main new features and examples or instructions on how to use them -->
- `ConfigManagingActor`: The file polling mechanism is now forced by default. Two new parameters have been added:
- `force_polling`: Whether to force file polling to check for changes. Default is `True`.
- `polling_interval`: The interval to check for changes. Only relevant if polling is enabled. Default is 1 second.

## Bug Fixes

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ dependencies = [
# changing the version
# (plugins.mkdocstrings.handlers.python.import)
"frequenz-client-microgrid >= 0.5.1, < 0.6.0",
"frequenz-channels >= 1.1.0, < 2.0.0",
"frequenz-channels >= 1.2.0, < 2.0.0",
"networkx >= 2.8, < 4",
"numpy >= 1.26.4, < 2",
"typing_extensions >= 4.6.1, < 5",
Expand Down
14 changes: 13 additions & 1 deletion src/frequenz/sdk/config/_config_managing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pathlib
import tomllib
from collections import abc
from datetime import timedelta
from typing import Any, assert_never

from frequenz.channels import Sender
Expand All @@ -29,13 +30,16 @@ class ConfigManagingActor(Actor):
reading too.
"""

# pylint: disable-next=too-many-arguments
def __init__(
self,
config_path: pathlib.Path | str,
output: Sender[abc.Mapping[str, Any]],
event_types: abc.Set[EventType] = frozenset(EventType),
*,
name: str | None = None,
force_polling: bool = True,
polling_interval: timedelta = timedelta(seconds=1),
) -> None:
"""Initialize this instance.

Expand All @@ -45,6 +49,9 @@ def __init__(
event_types: The set of event types to monitor.
name: The name of the actor. If `None`, `str(id(self))` will
be used. This is used mostly for debugging purposes.
force_polling: Whether to force file polling to check for changes.
polling_interval: The interval to poll for changes. Only relevant if
polling is enabled.
"""
super().__init__(name=name)
self._config_path: pathlib.Path = (
Expand All @@ -54,6 +61,8 @@ def __init__(
)
self._output: Sender[abc.Mapping[str, Any]] = output
self._event_types: abc.Set[EventType] = event_types
self._force_polling: bool = force_polling
self._polling_interval: timedelta = polling_interval

def _read_config(self) -> abc.Mapping[str, Any]:
"""Read the contents of the configuration file.
Expand Down Expand Up @@ -89,7 +98,10 @@ async def _run(self) -> None:
# parent directory instead just in case a configuration file doesn't exist yet
# or it is deleted and recreated again.
file_watcher = FileWatcher(
paths=[self._config_path.parent], event_types=self._event_types
paths=[self._config_path.parent],
event_types=self._event_types,
force_polling=self._force_polling,
polling_interval=self._polling_interval,
)

try:
Expand Down
8 changes: 6 additions & 2 deletions tests/actor/test_config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ async def test_update(self, config_file: pathlib.Path) -> None:
)
config_receiver = config_channel.new_receiver()

async with ConfigManagingActor(config_file, config_channel.new_sender()):
async with ConfigManagingActor(
config_file, config_channel.new_sender(), force_polling=False
):
config = await config_receiver.receive()
assert config is not None
assert config.get("logging_lvl") == "DEBUG"
Expand Down Expand Up @@ -100,7 +102,9 @@ async def test_update_relative_path(self, config_file: pathlib.Path) -> None:
current_dir = pathlib.Path.cwd()
relative_path = os.path.relpath(config_file, current_dir)

async with ConfigManagingActor(relative_path, config_channel.new_sender()):
async with ConfigManagingActor(
relative_path, config_channel.new_sender(), force_polling=False
):
config = await config_receiver.receive()
assert config is not None
assert config.get("var2") is None
Expand Down
2 changes: 1 addition & 1 deletion tests/timeseries/_battery_pool/test_battery_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -1306,7 +1306,7 @@ async def run_power_bounds_test( # pylint: disable=too-many-locals

# One inverter stopped sending data, use one remaining inverter
await streamer.stop_streaming(next(iter(bat_invs_map[batteries_in_pool[0]])))
await asyncio.sleep(MAX_BATTERY_DATA_AGE_SEC + 0.2)
await asyncio.sleep(MAX_BATTERY_DATA_AGE_SEC + 0.1)
msg = await asyncio.wait_for(receiver.receive(), timeout=waiting_time_sec)
compare_messages(
msg,
Expand Down
Loading