Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2d282e4
Bump the minimum required channels version to v1.4.0
llucax Nov 22, 2024
b67acd6
Add a `ConfigManager` class
llucax Nov 15, 2024
29725c4
Add an option to wait for the first configuration
llucax Nov 22, 2024
2921ed8
Add option to only send changed configurations
llucax Nov 22, 2024
751d20e
Add support for subscribing to specific config keys
llucax Nov 22, 2024
3ccb4eb
Add support for validating configurations with a schema
llucax Nov 28, 2024
e39cd6b
Add support to filter a sub-key
llucax Nov 25, 2024
3129c42
Assert the receiver has the correct type
llucax Dec 6, 2024
63c96a0
Add support for skipping `None` configs
llucax Dec 6, 2024
77295dc
Add a global instance for the config manager
llucax Nov 22, 2024
cd08feb
Support using `BackgroundService` as a *mixin*
llucax Dec 6, 2024
fbe18de
Add a base config schema that provides quantities support
llucax Dec 6, 2024
3201348
Add a `Reconfigurable` *mixin*
llucax Dec 6, 2024
2878a2a
Make the `LoggingConfigUpdatingActor` `Reconfigurable`
llucax Dec 9, 2024
0b54413
Allow configuring logging via `ConfigManager`
llucax Dec 9, 2024
80fc626
Revert "Make the `LoggingConfigUpdatingActor` `Reconfigurable`"
llucax Dec 10, 2024
c34c199
Revert "Add a `Reconfigurable` *mixin*"
llucax Dec 10, 2024
05164ef
Revert "Support using `BackgroundService` as a *mixin*"
llucax Dec 10, 2024
dcd76fb
Revert "Add a global instance for the config manager"
llucax Dec 10, 2024
9215c15
WIP: Add full example in the `config` module.
llucax Nov 22, 2024
40dcc3f
Revert "Add an option to wait for the first configuration"
llucax Dec 10, 2024
1f96cec
Improve logging for configuration file reading
llucax Dec 10, 2024
61d4b11
Remove support for receiving raw mapping as configuration
llucax Dec 10, 2024
0cc7e94
Move note about update bursts to Skipping superfluous updates
llucax Dec 10, 2024
4189066
Exclude unknown fields from the config by default
llucax Dec 10, 2024
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: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ dependencies = [
# changing the version
# (plugins.mkdocstrings.handlers.python.import)
"frequenz-client-microgrid >= 0.6.0, < 0.7.0",
"frequenz-channels >= 1.2.0, < 2.0.0",
"frequenz-quantities >= 1.0.0rc3, < 2.0.0",
"frequenz-channels >= 1.4.0, < 2.0.0",
"frequenz-quantities[marshmallow] >= 1.0.0, < 2.0.0",
"networkx >= 2.8, < 4",
"numpy >= 1.26.4, < 2",
"typing_extensions >= 4.6.1, < 5",
Expand Down
67 changes: 66 additions & 1 deletion src/frequenz/sdk/config/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,78 @@
# License: MIT
# Copyright © 2024 Frequenz Energy-as-a-Service GmbH

"""Read and update config variables."""
"""Configuration management.

Example: App configuring the global config manager.
```python
import asyncio
import dataclasses
import sys

import marshmallow

from frequenz.channels import select, selected_from
from frequenz.sdk.actor import Actor
from frequenz.sdk.config import (
initialize_config,
config_manager,
LoggingConfigUpdatingActor,
ConfigManager,
)

@dataclasses.dataclass
class ActorConfig:
name: str

class MyActor(Actor):
def __init__(self, config: ActorConfig) -> None:
self._config = config
super().__init__()

async def _run(self) -> None:
receiver = ...
config_receiver = await config_manager().new_receiver(schema=ActorConfig)

async for selected in select(receiver, config_receiver):
if selected_from(selected, receiver):
...
elif selected_from(selected, config_receiver):
self._config = selected.message
# Restart whatever is needed after a config update


@dataclasses.dataclass
class AppConfig:
positive_int: int = dataclasses.field(
default=42,
metadata={"validate": marshmallow.validate.Range(min=0)},
)
my_actor: ActorConfig | None = None
logging: LoggingConfig = LoggingConfig()

async def main() -> None:
config_manager = initialize_config_manager(["config.toml"])
try:
# Receive the first configuration
initial_config = await config_manager.new_receiver(schema=AppConfig,
wait_for_first=True)
except asyncio.TimeoutError:
print("No configuration received in time")
sys.exit(1)

actor = MyActor(ActorConfig(name=initial_config.my_actor))
actor.start()
await actor
```
"""

from ._logging_actor import LoggerConfig, LoggingConfig, LoggingConfigUpdatingActor
from ._manager import ConfigManager
from ._managing_actor import ConfigManagingActor
from ._util import load_config

__all__ = [
"ConfigManager",
"ConfigManagingActor",
"LoggerConfig",
"LoggingConfig",
Expand Down
10 changes: 10 additions & 0 deletions src/frequenz/sdk/config/_base_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# License: MIT
# Copyright © 2024 Frequenz Energy-as-a-Service GmbH

"""Base schema for configuration classes."""

from frequenz.quantities.experimental.marshmallow import QuantitySchema


class BaseConfigSchema(QuantitySchema):
"""A base schema for configuration classes."""
Comment on lines +9 to +10
Copy link
Contributor

@ela-kotulska-frequenz ela-kotulska-frequenz Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Just wondering, why you create BaseConfigSchema?
    User can just use QuantitySchema

  2. BaseConfigSchema is not used anywhere

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Just wondering, why you create BaseConfigSchema?
    User can just use QuantitySchema

TL;DR: It is mostly to have a more future-proof API.

Maybe it is over-engineering for now, but my thought was that users might want to inherit from BaseConfigSchema and add their own custom fields. If in the future we have some other library providing a base schema like QuantitySchema, we can make BaseConfigSchema inherit from that too, and the user's code doesn't need to change, it will automatically get the new fields if they are inheriting from BaseConfigSchema.

If we use QuantitySchema (so users inherit from that), and then we want to ship a base schema with more fields than QuantitySchema, the users will either need to update their code to now inherit from BaseConfigSchema, or they won't get the new fields.

  1. BaseConfigSchema is not used anywhere

Yeah, draft PR :-P Fixed in the new version.

Loading
Loading