Skip to content

Commit

Permalink
Add polling parameters to ConfigManagingActor
Browse files Browse the repository at this point in the history
The ConfigManagingActor now allows to force file polling
and set the polling interval.

Signed-off-by: Daniel Zullo <daniel.zullo@frequenz.com>
  • Loading branch information
daniel-zullo-frequenz committed Oct 1, 2024
1 parent 2e7a096 commit ecd11b8
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 5 deletions.
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

0 comments on commit ecd11b8

Please sign in to comment.