Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
85a18dc
feat: Add enabled/disabled toggle for feature views
rpathade May 13, 2026
5e98c7f
feat: Add demo noteboooks for users
ntkathole May 8, 2026
f735cd2
feat: Add CLI enable/disable commands and registry metadata support
rpathade May 15, 2026
426ae09
Added features
rpathade May 16, 2026
365ecb4
fix(compute-engine/local): Honor field_mapping on join keys in dedup …
1fanwang May 13, 2026
5b94d4d
feat: Add Prometheus gauges for FeatureStore installation telemetry (…
ntkathole May 13, 2026
b5297b8
docs: Rename Atlas Vector Search to MongoDB Vector Search and fix cod…
jvincent-mongodb May 13, 2026
04d500c
feat(dynamodb): Use ProjectionExpression when requested_features is set
Jwrede May 3, 2026
c9e368b
fix(dynamodb): Fix mypy type for _build_projection_expression return
Jwrede May 3, 2026
de050ab
fix(bigquery): Enable list inference for parquet loads in offline_wri…
Jwrede May 3, 2026
78fcd72
fix(trino): Clean up temporary entity tables after retrieval (#6381)
Jwrede May 14, 2026
2014acd
feat(bigquery): Support DATE-type event timestamp columns (#6362)
Jwrede May 14, 2026
5e69e5f
fix: Fixes for ray source
ntkathole May 14, 2026
53e4a92
feat: Expose registry endpoints on feature server for MCP access
patelchaitany Apr 21, 2026
e9791b0
fix: Revert state propagation to always update in _update_metadata_fi…
rpathade May 16, 2026
f7fd0f8
fix: Recompile protos for protobuf 4.x compatibility and fix state ma…
rpathade May 18, 2026
a4f7ab8
feat: Add unit tests for state machine and clean up lazy imports in r…
rpathade May 18, 2026
3aa8778
fix: Address review comments for feature view state management
rpathade May 20, 2026
e626433
fix: Resolve integration test failures in apply loop
rpathade May 20, 2026
8130b63
fix: Resolve integration test failures in apply loop
rpathade May 20, 2026
2b54bd0
Apply suggestion from @ntkathole
rpathade May 21, 2026
cb33b6d
fix: Resolve review comments for feature_store
rpathade May 21, 2026
f3b94eb
fix: Resolve review comments for feature_views.py
rpathade May 21, 2026
a4c85dc
Merge branch 'master' into feat/feature-view-enabled-disabled-v2
rpathade May 21, 2026
abb6a41
Merge remote-tracking branch 'origin/master' into feat/feature-view-e…
rpathade May 21, 2026
f4dd0a4
feat: Add FeatureStore methods and update describe for enabled/state
rpathade May 22, 2026
a3f65b0
Merge branch 'master' into feat/feature-view-enabled-disabled-v2
rpathade May 22, 2026
efd41a6
fix: Add type: ignore comments for mypy on BaseFeatureView attr access
rpathade May 22, 2026
436a712
fix: Remove REST API endpoints for enable/disable/set-state (deferred…
rpathade May 22, 2026
7110346
Merge remote-tracking branch 'origin/master' into feat/feature-view-e…
rpathade May 22, 2026
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
fix: Resolve review comments for feature_store
Signed-off-by: RutujaPathade <73137503+RutujaPathade@users.noreply.github.com>
  • Loading branch information
rpathade committed May 21, 2026
commit cb33b6df04e2693133eee90bb05d3905fd3e4bb9
9 changes: 1 addition & 8 deletions sdk/python/feast/diff/registry_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,15 +404,8 @@ def apply_diff_to_registry(
FeastObjectType.ON_DEMAND_FEATURE_VIEW,
FeastObjectType.STREAM_FEATURE_VIEW,
]:
new_fv = cast(BaseFeatureView, feast_object_diff.new_feast_object)
# Preserve lifecycle state from the existing registry object so
# that ``feast apply`` does not reset e.g. AVAILABLE_ONLINE back
# to STATE_UNSPECIFIED.
existing_fv = feast_object_diff.current_feast_object
if existing_fv is not None and hasattr(existing_fv, "state"):
new_fv.state = existing_fv.state # type: ignore[attr-defined]
registry.apply_feature_view(
new_fv,
cast(BaseFeatureView, feast_object_diff.new_feast_object),
project,
commit=False,
no_promote=no_promote,
Expand Down
59 changes: 34 additions & 25 deletions sdk/python/feast/feature_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -1205,33 +1205,12 @@ def apply(
services_to_update,
)

# Preserve lifecycle state from the registry so that apply does
# not reset e.g. AVAILABLE_ONLINE back to STATE_UNSPECIFIED.
# Must run before any commit=False operations to avoid registry
# cache refreshes that would discard uncommitted changes.
existing_states: dict[str, FeatureViewState] = {}
for view in itertools.chain(views_to_update, odfvs_to_update, sfvs_to_update):
if (
hasattr(view, "state")
and view.state == FeatureViewState.STATE_UNSPECIFIED
):
try:
existing = self.registry.get_any_feature_view(
view.name, self.project
)
if hasattr(existing, "state"):
existing_states[view.name] = existing.state
except FeastObjectNotFoundException:
pass

# Add all objects to the registry and update the provider's infrastructure.
for project in projects_to_update:
self.registry.apply_project(project, commit=False)
for ds in data_sources_to_update:
self.registry.apply_data_source(ds, project=self.project, commit=False)
for view in itertools.chain(views_to_update, odfvs_to_update, sfvs_to_update):
if view.name in existing_states:
view.state = existing_states[view.name] # type: ignore[attr-defined]
self.registry.apply_feature_view(
view, project=self.project, commit=False, no_promote=no_promote
)
Expand Down Expand Up @@ -1856,8 +1835,19 @@ def tqdm_builder(length):
end_date = utils.make_tzaware(end_date) or _utc_now()

# Transition state to MATERIALIZING before starting.
# Only enforce when the state machine is active (not STATE_UNSPECIFIED).
previous_state = getattr(feature_view, "state", None)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Similar to cli, can_transition_to() check can be enforced here as well

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added can_transition_to() check in both materialization paths, guarded with state != STATE_UNSPECIFIED for backward compatibility.

if hasattr(feature_view, "state"):
if (
hasattr(feature_view, "state")
and feature_view.state != FeatureViewState.STATE_UNSPECIFIED
):
if not feature_view.state.can_transition_to(
FeatureViewState.MATERIALIZING
):
raise ValueError(
f"FeatureView {feature_view.name} cannot transition "
f"from {feature_view.state.name} to MATERIALIZING."
)
feature_view.state = FeatureViewState.MATERIALIZING
self.registry.apply_feature_view(
feature_view, self.project, commit=True
Expand All @@ -1878,7 +1868,11 @@ def tqdm_builder(length):
except Exception:
fv_success = False
# Roll back state to previous value on failure.
if hasattr(feature_view, "state") and previous_state is not None:
if (
hasattr(feature_view, "state")
and previous_state is not None
and previous_state != FeatureViewState.STATE_UNSPECIFIED
):
feature_view.state = previous_state
self.registry.apply_feature_view(
feature_view, self.project, commit=True
Expand Down Expand Up @@ -1998,8 +1992,19 @@ def tqdm_builder(length):
end_date = utils.make_tzaware(end_date)

# Transition state to MATERIALIZING before starting.
# Only enforce when the state machine is active (not STATE_UNSPECIFIED).
previous_state = getattr(feature_view, "state", None)
if hasattr(feature_view, "state"):
if (
hasattr(feature_view, "state")
and feature_view.state != FeatureViewState.STATE_UNSPECIFIED
):
if not feature_view.state.can_transition_to(
FeatureViewState.MATERIALIZING
):
raise ValueError(
f"FeatureView {feature_view.name} cannot transition "
f"from {feature_view.state.name} to MATERIALIZING."
)
feature_view.state = FeatureViewState.MATERIALIZING
self.registry.apply_feature_view(
feature_view, self.project, commit=True
Expand All @@ -2021,7 +2026,11 @@ def tqdm_builder(length):
except Exception:
fv_success = False
# Roll back state to previous value on failure.
if hasattr(feature_view, "state") and previous_state is not None:
if (
hasattr(feature_view, "state")
and previous_state is not None
and previous_state != FeatureViewState.STATE_UNSPECIFIED
):
feature_view.state = previous_state
self.registry.apply_feature_view(
feature_view, self.project, commit=True
Expand Down
8 changes: 6 additions & 2 deletions sdk/python/feast/infra/registry/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,10 +584,14 @@ def _update_metadata_fields(
if hasattr(existing_proto.spec, "disabled") and hasattr(updated_fv, "enabled"):
existing_proto.spec.disabled = not getattr(updated_fv, "enabled")

# Lifecycle state
# Lifecycle state — skip STATE_UNSPECIFIED so that ``feast apply``
# does not accidentally reset an AVAILABLE_ONLINE view.
if hasattr(existing_proto.meta, "state") and hasattr(updated_fv, "state"):
state_val = getattr(updated_fv, "state")
if isinstance(state_val, FeatureViewState):
if (
isinstance(state_val, FeatureViewState)
and state_val != FeatureViewState.STATE_UNSPECIFIED
):
existing_proto.meta.state = state_val.to_proto()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Every feast apply resets all feature views back to CREATED, even if they were already AVAILABLE_ONLINE

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

both feast apply paths now preserve the existing state from the registry instead of overwriting it with the default STATE_UNSPECIFIED. Works across all registry backends.


# OnDemandFeatureView configuration
Expand Down