2121from ets .core .config_comparison import compare_configs
2222from ets .core .config_pruning import prune_unproductive_subgraphs
2323from ets .core .config_validation import ConfigValidationError , validate
24- from ets .core .model_derivation import ModelDeriver
24+ from ets .core .model_derivation import ModelDerivationError , ModelDeriver
2525from ets .core .models import PersistedConfig , RawConfig
26- from ets .ports .inbound .config_manager import ConfigManagerError , ConfigManagerPort
2726from ets .ports .outbound .config_loader import ConfigLoaderPort
2827from ets .ports .outbound .config_version import ConfigVersionerPort
2928from ets .ports .outbound .config_writer import ConfigWriterPort
3029
3130log = logging .getLogger (__name__ )
3231
3332
34- class ConfigManager (ConfigManagerPort ):
33+ class ConfigManagerError (RuntimeError ):
34+ """Raised when an unexpected error happens while handling a transformation configuration."""
35+
36+
37+ class ConfigManager :
3538 """Manages loading, comparison, validation and selection of an active config."""
3639
3740 def __init__ (
@@ -64,7 +67,7 @@ def known_version(self) -> int:
6467 return self ._known_version
6568
6669 async def update_config (self ):
67- """Return the active config and its version, reloading from DB if the version changed."""
70+ """Check if the active config is stale and reload from DB if the version changed."""
6871 current_version = await self ._versioner .get_version ()
6972 if self ._current_config is None :
7073 log .info ("Loading initial config (version %d)." , current_version )
@@ -86,7 +89,7 @@ async def update_config(self):
8689 log .critical (inconsistent_version )
8790 raise inconsistent_version
8891
89- async def resolve_and_persist (self , input_config_path : Path ) -> None :
92+ async def resolve_and_persist (self , input_config_path : Path ) -> bool :
9093 """Load, resolve, and persist the transformation config.
9194
9295 - Loads the raw config from disk and the persisted one from the database.
@@ -100,19 +103,28 @@ async def resolve_and_persist(self, input_config_path: Path) -> None:
100103 Raises:
101104 ConfigManagerError: If the new config fails validation and no previous
102105 valid config exists in the database.
106+ Returns:
107+ True, if the persisted config is outdated and has been replaced with a new one
108+ False in all other cases
103109 """
104110 raw_config = self ._loader .load_config_from_file (input_config_path )
105111 persisted_config = await self ._loader .load_config_from_db ()
106112
107- await self ._resolve (raw_config = raw_config , persisted_config = persisted_config )
113+ return await self ._resolve_has_config_changed (
114+ raw_config = raw_config , persisted_config = persisted_config
115+ )
108116
109- async def _resolve (
117+ async def _resolve_has_config_changed (
110118 self , * , raw_config : RawConfig , persisted_config : PersistedConfig
111- ):
112- """Compare, validate/prune and derive schemas as needed."""
119+ ) -> bool :
120+ """Compare, validate/prune, derive schemas and persist the config as needed.
121+ Returns:
122+ True, if the persisted config is outdated and has been replaced with a new one
123+ False in all other cases
124+ """
113125 result = compare_configs (raw_config , persisted_config )
114126 if not isinstance (result , RawConfig ):
115- return
127+ return False
116128
117129 try :
118130 validated = validate (raw_config )
@@ -134,11 +146,21 @@ async def _resolve(
134146 log .warning (
135147 "New config failed to validate, using existing, persisted config instead."
136148 )
137- return persisted_config
138- derived_models = self ._model_deriver .derive_models (pruned )
149+ return False
150+
151+ try :
152+ derived_models = self ._model_deriver .derive_models (pruned )
153+ except ModelDerivationError :
154+ log .warning (
155+ "Could not derive model schemas for new configuration."
156+ + "\n Falling back to existing, persisted config instead."
157+ )
158+ return False
159+
139160 resolved = PersistedConfig (
140161 models = derived_models ,
141162 routes = pruned .routes ,
142163 workflows = pruned .workflows ,
143164 )
144165 await self ._writer .write_config (resolved )
166+ return True
0 commit comments