Skip to content

Commit

Permalink
Fix ConfigManagingActor to handle missing config files gracefully
Browse files Browse the repository at this point in the history
Eliminate recursive actor crashes when config files are missing.
The previous implementation suffered from a critical error pattern:
- The `_read_config` method is called at the start of the `_run` method
  and on FileWatcher event.
- When no config files existed, an exception would be raised
- This exception caused the actor to crash and immediately restart
- Restarting triggered the same `_read_config` method
- The cycle repeated, creating a persistent crash loop

This fix introduces a more robust approach:
- Detect missing config files without throwing exceptions
- Set up a FileWatcher to monitor for future config file creation
- call `_read_config` method as soon as any config file is crated.

Signed-off-by: Elzbieta Kotulska <[email protected]>
  • Loading branch information
ela-kotulska-frequenz committed Nov 28, 2024
1 parent 003ac25 commit d8655e3
Showing 1 changed file with 7 additions and 6 deletions.
13 changes: 7 additions & 6 deletions src/frequenz/sdk/config/_config_managing.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,11 @@ def __init__(
self._force_polling: bool = force_polling
self._polling_interval: timedelta = polling_interval

def _read_config(self) -> abc.Mapping[str, Any]:
def _read_config(self) -> abc.Mapping[str, Any] | None:
"""Read the contents of the configuration file.
Returns:
A dictionary containing configuration variables.
Raises:
ValueError: If config file cannot be read.
"""
error_count = 0
config: dict[str, Any] = {}
Expand All @@ -138,14 +135,18 @@ def _read_config(self) -> abc.Mapping[str, Any]:
error_count += 1

if error_count == len(self._config_paths):
raise ValueError(f"{self}: Can't read any of the config files")
_logger.error(
"%s: Can't read any of the config files, ignoring config update.", self
)
return None

return config

async def send_config(self) -> None:
"""Send the configuration to the output sender."""
config = self._read_config()
await self._output.send(config)
if config is not None:
await self._output.send(config)

async def _run(self) -> None:
"""Monitor for and send configuration file updates.
Expand Down

0 comments on commit d8655e3

Please sign in to comment.