Visitar URL original
fix(postgres): Use end_date in synthetic entity_df for non-entity retrieval by YassinNouh21 · Pull Request #6110 · feast-dev/feast · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -159,25 +159,26 @@ def get_historical_features(
else:
start_date = make_tzaware(start_date)

entity_df = pd.DataFrame(
{
"event_timestamp": pd.date_range(
start=start_date, end=end_date, freq="1s", tz=timezone.utc
)[:1] # Just one row
}
)
entity_df = pd.DataFrame({"event_timestamp": [end_date]})
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.

entity_schema = _get_entity_schema(entity_df, config)

entity_df_event_timestamp_col = (
offline_utils.infer_event_timestamp_from_entity_df(entity_schema)
)

entity_df_event_timestamp_range = _get_entity_df_event_timestamp_range(
entity_df,
entity_df_event_timestamp_col,
config,
)
# In non-entity mode, use the actual requested range so that
# min_event_timestamp (= range[0] - TTL) doesn't clip the window.
# The synthetic entity_df only has end_date, which would wrongly
# set min_event_timestamp to end_date - TTL instead of start_date - TTL.
if start_date is not None and end_date is not None:
entity_df_event_timestamp_range = (start_date, end_date)
else:
entity_df_event_timestamp_range = _get_entity_df_event_timestamp_range(
entity_df,
entity_df_event_timestamp_col,
config,
)

@contextlib.contextmanager
def query_generator() -> Iterator[str]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,71 @@ def test_non_entity_mode_with_both_dates(self):
assert "start_date" not in str(e)
assert "end_date" not in str(e)

def test_non_entity_entity_df_uses_end_date(self):
"""Test that the synthetic entity_df uses end_date, not start_date.
Regression test: the old code used pd.date_range(start=start_date, ...)[:1]
which put start_date in the entity_df. Since PIT joins use
MAX(entity_timestamp) as the upper bound, start_date made end_date
unreachable. The fix uses [end_date] directly.
"""
test_repo_config = RepoConfig(
project="test_project",
registry="test_registry",
provider="local",
offline_store=_mock_offline_store_config(),
)

feature_view = _mock_feature_view("test_fv", ttl=timedelta(days=1))
start_date = datetime(2023, 1, 1, tzinfo=timezone.utc)
end_date = datetime(2023, 1, 7, tzinfo=timezone.utc)

mock_get_entity_schema = MagicMock(
return_value={"event_timestamp": "timestamp"}
)

with (
patch.multiple(
"feast.infra.offline_stores.contrib.postgres_offline_store.postgres",
_get_conn=MagicMock(),
_upload_entity_df=MagicMock(),
_get_entity_schema=mock_get_entity_schema,
_get_entity_df_event_timestamp_range=MagicMock(
return_value=(start_date, end_date)
),
),
patch(
"feast.infra.offline_stores.contrib.postgres_offline_store.postgres.offline_utils.get_expected_join_keys",
return_value=[],
),
patch(
"feast.infra.offline_stores.contrib.postgres_offline_store.postgres.offline_utils.assert_expected_columns_in_entity_df",
),
patch(
"feast.infra.offline_stores.contrib.postgres_offline_store.postgres.offline_utils.get_feature_view_query_context",
return_value=[],
),
):
PostgreSQLOfflineStore.get_historical_features(
config=test_repo_config,
feature_views=[feature_view],
feature_refs=["test_fv:feature1"],
entity_df=None,
registry=MagicMock(),
project="test_project",
start_date=start_date,
end_date=end_date,
)

# _get_entity_schema is called with the synthetic entity_df
df = mock_get_entity_schema.call_args[0][0]
assert len(df) == 1
ts = df["event_timestamp"].iloc[0]
# The entity_df must use end_date, not start_date
assert ts == end_date, (
f"entity_df timestamp should be end_date ({end_date}), got {ts}"
)

def test_non_entity_mode_with_end_date_only(self):
"""Test non-entity retrieval calculates start_date from TTL"""
test_repo_config = RepoConfig(
Expand Down
Loading