Repository navigation
feast delete reports success for a SavedDataset but does not remove it from the registry #7044
Description
Expected Behavior
According to the CLI reference, feast delete <OBJECT_NAME> searches across all object types, including saved datasets, and deletes the first match. Running feast delete my_dataset on a registered SavedDataset should remove it from the registry.
Current Behavior
The command finds the saved dataset and prints Deleted SavedDataset my_dataset from demo. with exit code 0, but the saved dataset is still in the registry afterwards.
The cause is in FeatureStore.apply(). The delete command finds the object via store.get_saved_dataset and then calls store.apply([e], objects_to_delete=[e], partial=False). The if not partial: branch of apply() handles entities, feature views, ODFVs, stream feature views, feature services, data sources, validation references, permissions, and label views, but not SavedDataset, so the object is silently ignored.
The same thing happens when calling the SDK directly: store.apply([], objects_to_delete=[saved_dataset], partial=False) is a no-op for saved datasets.
Steps to reproduce
import os
import tempfile
from datetime import datetime, timezone
import pandas as pd
from click.testing import CliRunner
from feast import FeatureStore
from feast.cli.cli import cli
from feast.infra.offline_stores.file_source import SavedDatasetFileStorage
from feast.saved_dataset import SavedDataset
repo = tempfile.mkdtemp()
with open(os.path.join(repo, "feature_store.yaml"), "w") as f:
f.write(
"project: demo\n"
"provider: local\n"
"registry: registry.db\n"
"online_store:\n type: sqlite\n path: online.db\n"
"entity_key_serialization_version: 3\n"
)
path = os.path.join(repo, "ds.parquet")
pd.DataFrame(
{"id": [1], "f1": [1.0], "event_timestamp": [pd.Timestamp.now(tz="UTC")]}
).to_parquet(path)
store = FeatureStore(repo_path=repo)
ds = SavedDataset(
name="my_dataset",
features=["fv:f1"],
join_keys=["id"],
storage=SavedDatasetFileStorage(path=path),
)
ds.min_event_timestamp = datetime(2024, 1, 1, tzinfo=timezone.utc)
ds.max_event_timestamp = datetime(2024, 2, 1, tzinfo=timezone.utc)
store.registry.apply_saved_dataset(ds, "demo", commit=True)
result = CliRunner().invoke(cli, ["--chdir", repo, "delete", "my_dataset"])
print(result.output)
store = FeatureStore(repo_path=repo)
print([d.name for d in store.registry.list_saved_datasets("demo", allow_cache=False)])Output:
Deleted SavedDataset my_dataset from demo.
['my_dataset']
Specifications
- Version: master (c9b9d72, after 0.67.0)
- Platform: Windows 11, Python 3.12 (the affected code is platform independent)
- Subsystem: Python SDK / CLI (
feast delete,FeatureStore.apply)
Possible Solution
In the if not partial: branch of FeatureStore.apply(), collect SavedDataset instances from objects_to_delete and call self.registry.delete_saved_dataset(...) for each, in the same way validation references are handled. delete_saved_dataset already exists on all registry backends, so no registry changes are needed. A unit test that registers a saved dataset, deletes it through apply(..., partial=False), and asserts it is gone would cover the fix.
I'd be happy to open a PR for this.
Activity