Visitar URL original
feat: Add enabled/disabled toggle for feature views by rpathade · Pull Request #6401 · feast-dev/feast · GitHub
Skip to content
Merged
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(trino): Clean up temporary entity tables after retrieval (#6381)
* fix(trino): Clean up temporary entity tables after retrieval

TrinoOfflineStore.get_historical_features() creates a temporary table
for the entity DataFrame but never drops it, leaking tables
indefinitely. Apply the same context manager pattern used by
BigQuery, Redshift, and Athena offline stores: wrap the query in a
generator that issues DROP TABLE IF EXISTS in a finally block.

Fixes #6306

Signed-off-by: Jonathan Wrede <wrede.jonathan00@gmail.com>

* fix: sort imports for ruff compliance

Signed-off-by: Jonathan Wrede <wrede.jonathan00@gmail.com>

* fix: decouple temp table cleanup from query access

Avoid dropping the temporary entity table on to_sql() calls.
Previously, every method used a context manager that dropped
the table on exit, so calling to_sql() before to_df() would
destroy the table and cause subsequent queries to fail.

Now the query is stored as a plain string and cleanup is
handled by a dedicated _drop_temp_table() method called only
after query execution (to_df, to_trino). A __del__ fallback
ensures cleanup if execution methods are never called. The
_cleaned_up flag makes the drop idempotent.

Signed-off-by: Jonathan Wrede <wrede.jonathan00@gmail.com>

---------

Signed-off-by: Jonathan Wrede <wrede.jonathan00@gmail.com>
Signed-off-by: RutujaPathade <73137503+RutujaPathade@users.noreply.github.com>
  • Loading branch information
Jwrede authored and rpathade committed May 21, 2026
commit 78fcd7257677fe4e1d309ff149888f3578dc55f7
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import logging
import uuid
from datetime import date, datetime
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
from typing import (
Any,
Dict,
List,
Literal,
Optional,
Tuple,
Union,
)

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -37,6 +46,8 @@
from feast.repo_config import FeastConfigBaseModel, RepoConfig
from feast.saved_dataset import SavedDatasetStorage

logger = logging.getLogger(__name__)


class BasicAuthModel(FeastConfigBaseModel):
username: StrictStr
Expand Down Expand Up @@ -183,13 +194,16 @@ def __init__(
full_feature_names: bool,
on_demand_feature_views: Optional[List[OnDemandFeatureView]] = None,
metadata: Optional[RetrievalMetadata] = None,
temp_table: Optional[str] = None,
):
self._query = query
self._client = client
self._config = config
self._full_feature_names = full_feature_names
self._on_demand_feature_views = on_demand_feature_views or []
self._metadata = metadata
self._temp_table = temp_table
self._cleaned_up = False

@property
def full_feature_names(self) -> bool:
Expand All @@ -199,11 +213,29 @@ def full_feature_names(self) -> bool:
def on_demand_feature_views(self) -> List[OnDemandFeatureView]:
return self._on_demand_feature_views

def _drop_temp_table(self) -> None:
if self._cleaned_up or not self._temp_table:
return
self._cleaned_up = True
try:
self._client.execute_query(f"DROP TABLE IF EXISTS {self._temp_table}")
except Exception:
logger.exception(
"Failed to drop temporary entity table %s",
self._temp_table,
)

def __del__(self) -> None:
self._drop_temp_table()

def _to_df_internal(self, timeout: Optional[int] = None) -> pd.DataFrame:
"""Return dataset as Pandas DataFrame synchronously including on demand transforms"""
results = self._client.execute_query(query_text=self._query)
self.pyarrow_schema = results.pyarrow_schema
return results.to_dataframe()
try:
results = self._client.execute_query(query_text=self._query)
self.pyarrow_schema = results.pyarrow_schema
return results.to_dataframe()
finally:
self._drop_temp_table()

def _to_arrow_internal(self, timeout: Optional[int] = None) -> pyarrow.Table:
"""Return payrrow dataset as synchronously including on demand transforms"""
Expand Down Expand Up @@ -234,8 +266,11 @@ def to_trino(
destination_table = f"{self._client.catalog}.{self._config.offline_store.dataset}.historical_{today}_{rand_id}"

# TODO: Implement the timeout logic
query = f"CREATE TABLE {destination_table} AS ({self._query})"
self._client.execute_query(query_text=query)
try:
create_query = f"CREATE TABLE {destination_table} AS ({self._query})"
self._client.execute_query(query_text=create_query)
finally:
self._drop_temp_table()
return destination_table

def persist(
Expand Down Expand Up @@ -372,11 +407,12 @@ def get_historical_features(
)

# Generate the Trino SQL query from the query context
entity_table_ref = table_reference
if type(entity_df) is str:
table_reference = f"({entity_df})"
entity_table_ref = f"({entity_df})"
query = offline_utils.build_point_in_time_query(
query_context,
left_table_query_string=table_reference,
left_table_query_string=entity_table_ref,
entity_df_event_timestamp_col=entity_df_event_timestamp_col,
entity_df_columns=entity_schema.keys(),
query_template=MULTIPLE_FEATURE_VIEW_POINT_IN_TIME_JOIN,
Expand All @@ -385,6 +421,7 @@ def get_historical_features(

return TrinoRetrievalJob(
query=query,
temp_table=table_reference if isinstance(entity_df, pd.DataFrame) else None,
client=client,
config=config,
full_feature_names=full_feature_names,
Expand Down Expand Up @@ -483,8 +520,6 @@ def _upload_entity_df_and_get_entity_schema(
else:
raise InvalidEntityType(type(entity_df))

# TODO: Ensure that the table expires after some time


def _get_trino_client(config: RepoConfig) -> Trino:
auth = None
Expand Down