|
4 | 4 |
|
5 | 5 | import pytest |
6 | 6 |
|
| 7 | +from feast import utils |
7 | 8 | from feast.data_format import AvroFormat, ParquetFormat |
8 | 9 | from feast.data_source import KafkaSource |
9 | 10 | from feast.entity import Entity |
@@ -431,3 +432,52 @@ def test_materialize_disabled_fv_by_name_raises(self, local_feature_store): |
431 | 432 | end_date=datetime.utcnow(), |
432 | 433 | ) |
433 | 434 | store.teardown() |
| 435 | + |
| 436 | + |
| 437 | +# --------------------------------------------------------------------------- |
| 438 | +# Serving lifecycle gate: serve_features_while_materializing |
| 439 | +# --------------------------------------------------------------------------- |
| 440 | + |
| 441 | + |
| 442 | +class _StubRegistry: |
| 443 | + """Minimal registry stub exposing what _get_feature_views_to_use needs.""" |
| 444 | + |
| 445 | + def __init__(self, fv, serve_features_while_materializing=False): |
| 446 | + self._fv = fv |
| 447 | + self.serve_features_while_materializing = serve_features_while_materializing |
| 448 | + |
| 449 | + def get_any_feature_view(self, name, project, allow_cache=False): |
| 450 | + return self._fv |
| 451 | + |
| 452 | + |
| 453 | +class TestServeWhileMaterializingGate: |
| 454 | + def _fv_in_state(self, state): |
| 455 | + fv = _simple_feature_view() |
| 456 | + fv.state = state |
| 457 | + return fv |
| 458 | + |
| 459 | + def test_materializing_blocked_by_default(self): |
| 460 | + registry = _StubRegistry(self._fv_in_state(FeatureViewState.MATERIALIZING)) |
| 461 | + with pytest.raises(ValueError, match="cannot serve features"): |
| 462 | + utils._get_feature_views_to_use(registry, "default", ["test_fv:f1"]) |
| 463 | + |
| 464 | + def test_materializing_served_when_flag_enabled(self): |
| 465 | + registry = _StubRegistry( |
| 466 | + self._fv_in_state(FeatureViewState.MATERIALIZING), |
| 467 | + serve_features_while_materializing=True, |
| 468 | + ) |
| 469 | + fvs, _ = utils._get_feature_views_to_use(registry, "default", ["test_fv:f1"]) |
| 470 | + assert [fv.name for fv in fvs] == ["test_fv"] |
| 471 | + |
| 472 | + def test_available_online_served_regardless_of_flag(self): |
| 473 | + registry = _StubRegistry(self._fv_in_state(FeatureViewState.AVAILABLE_ONLINE)) |
| 474 | + fvs, _ = utils._get_feature_views_to_use(registry, "default", ["test_fv:f1"]) |
| 475 | + assert [fv.name for fv in fvs] == ["test_fv"] |
| 476 | + |
| 477 | + def test_created_still_blocked_even_with_flag(self): |
| 478 | + registry = _StubRegistry( |
| 479 | + self._fv_in_state(FeatureViewState.CREATED), |
| 480 | + serve_features_while_materializing=True, |
| 481 | + ) |
| 482 | + with pytest.raises(ValueError, match="cannot serve features"): |
| 483 | + utils._get_feature_views_to_use(registry, "default", ["test_fv:f1"]) |
0 commit comments