Skip to content

Commit bc3dfd5

Browse files
committed
Add option to only send changed configurations
When this option is enabled, configurations will be sent to the receiver only if they are different from the previously received configuration. Signed-off-by: Leandro Lucarella <[email protected]>
1 parent 9cc55cc commit bc3dfd5

File tree

1 file changed

+45
-5
lines changed

1 file changed

+45
-5
lines changed

src/frequenz/sdk/config/_manager.py

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@
33

44
"""Management of configuration."""
55

6+
import logging
67
import pathlib
78
from collections.abc import Mapping, Sequence
89
from datetime import timedelta
910
from typing import Any, Final
1011

1112
from frequenz.channels import Broadcast, Receiver
13+
from frequenz.channels.experimental import WithPrevious
1214
from typing_extensions import override
1315

1416
from ..actor._background_service import BackgroundService
1517
from ._managing_actor import ConfigManagingActor
1618

19+
_logger = logging.getLogger(__name__)
20+
1721

1822
class ConfigManager(BackgroundService):
1923
"""A manager for configuration files.
@@ -100,19 +104,55 @@ def __repr__(self) -> str:
100104
"""Return a string representation of this config manager."""
101105
return f"config_channel={self.config_channel!r}, " f"actor={self.actor!r}>"
102106

103-
async def new_receiver(self) -> Receiver[Mapping[str, Any] | None]:
107+
def new_receiver(
108+
self,
109+
*,
110+
skip_unchanged: bool = True,
111+
) -> Receiver[Mapping[str, Any] | None]:
104112
"""Create a new receiver for the configuration.
105113
106-
Note:
107-
If there is a burst of configuration updates, the receiver will only
108-
receive the last configuration, older configurations will be ignored.
114+
This method has a lot of features and functionalities to make it easier to
115+
receive configurations, but it also imposes some restrictions on how the
116+
configurations are received. If you need more control over the configuration
117+
receiver, you can create a receiver directly using
118+
[`config_channel.new_receiver()`][frequenz.sdk.config.ConfigManager.config_channel].
119+
120+
### Skipping superfluous updates
121+
122+
If there is a burst of configuration updates, the receiver will only receive the
123+
last configuration, older configurations will be ignored.
124+
125+
If `skip_unchanged` is set to `True`, then a configuration that didn't change
126+
compared to the last one received will be ignored and not sent to the receiver.
127+
The comparison is done using the *raw* `dict` to determine if the configuration
128+
has changed.
109129
110130
Example:
111131
```python
112132
# TODO: Add Example
113133
```
114134
135+
Args:
136+
skip_unchanged: Whether to skip sending the configuration if it hasn't
137+
changed compared to the last one received.
138+
115139
Returns:
116140
The receiver for the configuration.
117141
"""
118-
return self.config_channel.new_receiver(name=str(self), limit=1)
142+
receiver = self.config_channel.new_receiver(name=str(self), limit=1)
143+
144+
if skip_unchanged:
145+
receiver = receiver.filter(WithPrevious(not_equal_with_logging))
146+
147+
return receiver
148+
149+
150+
def not_equal_with_logging(
151+
old_config: Mapping[str, Any], new_config: Mapping[str, Any]
152+
) -> bool:
153+
"""Return whether the two mappings are not equal, logging if they are the same."""
154+
if old_config == new_config:
155+
_logger.info("Configuration has not changed, skipping update")
156+
_logger.debug("Old configuration being kept: %r", old_config)
157+
return False
158+
return True

0 commit comments

Comments
 (0)