Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Prev Previous commit
Next Next commit
feat: Warn on unsafe serve_features_while_materializing configs
Emit advisory (non-fatal) warnings when the flag is combined with a
non-sql registry (no-op) or cache_mode='thread' (state transitions may
be observed stale).

Signed-off-by: Alan Gauthier <alan.gauthier@jobteaser.com>
  • Loading branch information
alan-gauthier-jt authored and ntkathole committed Sep 29, 2026
commit c473fa3a2acfae750430495ea7d1c2aa86c5a5fb
24 changes: 24 additions & 0 deletions sdk/python/feast/repo_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,30 @@ def validate_path(cls, path: str, values: ValidationInfo) -> str:
return cls._normalize_postgres_scheme(path, "path")
return path

@model_validator(mode="after")
def _warn_on_unsafe_serve_while_materializing(self) -> "RegistryConfig":
"""Warn when ``serve_features_while_materializing`` is combined with a
registry configuration where it is a no-op or where its guarantees may
not hold. These are advisory warnings only, never hard failures.
"""
if self.serve_features_while_materializing:
if self.registry_type != "sql":
_logger.warning(
"`serve_features_while_materializing` is enabled but "
f"`registry_type` is '{self.registry_type}'. The flag targets "
"the serving interruption caused by concurrent servers sharing "
"a `sql` registry that materialization flips to `MATERIALIZING`; "
"on other registry types it typically has no effect."
)
if self.cache_mode == "thread":
_logger.warning(
"`serve_features_while_materializing` is enabled together with "
"`cache_mode='thread'`. In thread mode the registry cache may lag "
"by up to `cache_ttl_seconds`, so feature-view state transitions "
"(including the exit from `MATERIALIZING`) may be observed stale."
)
return self


class MaterializationConfig(BaseModel):
"""Configuration options for feature materialization behavior."""
Expand Down
44 changes: 44 additions & 0 deletions sdk/python/tests/unit/test_registry_string_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,47 @@ def test_pathlib_does_not_treat_s3_as_absolute(self):

joined = Path("/app").joinpath(s3_path)
assert str(joined).startswith("/app/s3:")


class TestServeWhileMaterializingWarnings:
"""`serve_features_while_materializing` emits advisory warnings when combined
with a registry configuration where the flag is a no-op or where its
guarantees may not hold. These are warnings only, never hard failures."""

def test_no_warning_when_flag_disabled(self, caplog):
with caplog.at_level("WARNING", logger="feast.repo_config"):
RegistryConfig(registry_type="sql")
assert "serve_features_while_materializing" not in caplog.text

def test_no_warning_for_safe_sql_sync_config(self, caplog):
with caplog.at_level("WARNING", logger="feast.repo_config"):
RegistryConfig(registry_type="sql", serve_features_while_materializing=True)
assert "serve_features_while_materializing" not in caplog.text

def test_warns_on_non_sql_registry(self, caplog):
with caplog.at_level("WARNING", logger="feast.repo_config"):
RegistryConfig(
registry_type="file", serve_features_while_materializing=True
)
assert "registry_type" in caplog.text
assert "cache_mode" not in caplog.text

def test_warns_on_thread_cache_mode(self, caplog):
with caplog.at_level("WARNING", logger="feast.repo_config"):
RegistryConfig(
registry_type="sql",
cache_mode="thread",
serve_features_while_materializing=True,
)
assert "cache_mode='thread'" in caplog.text
assert "registry_type" not in caplog.text

def test_warns_on_both_when_both_incompatible(self, caplog):
with caplog.at_level("WARNING", logger="feast.repo_config"):
RegistryConfig(
registry_type="file",
cache_mode="thread",
serve_features_while_materializing=True,
)
assert "registry_type" in caplog.text
assert "cache_mode='thread'" in caplog.text