| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
|
⚠️ Please install the Codecov Report❌ Patch coverage is 86.27451% with 14 lines in your changes missing coverage. Please review.
@@ Coverage Diff @@
## master #6718 +/- ##
==========================================
+ Coverage 46.92% 47.06% +0.13%
==========================================
Files 416 418 +2
Lines 50549 51753 +1204
Branches 7252 7505 +253
==========================================
+ Hits 23718 24355 +637
- Misses 25157 25667 +510
- Partials 1674 1731 +57
... and 56 files with indirect coverage changes Continue to review full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Sorry, something went wrong.
|
@ntkathole This PR doesnt introduce any dependency change, yet the CI is failing because it cant resolve greenlet 3.5.5 . I am not really sure where the error is coming from. Rebased my PR with the latest changed from main in case this error was resolved in a later commit and to trigger the CI again |
Sorry, something went wrong.
A FeatureService built from a version-pinned FeatureView (e.g.
FeatureView(version="v2")) silently served the promoted version instead
of the pinned one, defeating the guarantee a FeatureService is meant to
provide. Two bugs caused this:
1. FeatureService.__init__ appended the source view's projection without
translating its `version` string into `projection.version_tag` (the
field name_to_use() checks to render "fv@v2").
2. utils._get_feature_views_to_use hard-coded the version as None for the
FeatureService branch, so retrieval always fell through to the
promoted snapshot.
Stamp version_tag from the source view's version in __init__, and read
projection.version_tag (instead of None) during retrieval. The default
version ("latest") leaves version_tag as None, so every existing
unversioned FeatureService is unaffected. Covers both online and offline
retrieval, which share _get_feature_views_to_use.
Signed-off-by: h-sarwat <hussein_sarwat@yahoo.com>
FeatureService.features now accepts string refs using the same '<feature_view>[@<version>][:<feature>]' syntax as get_historical_features/get_online_features, e.g. "driver_stats@v2" or "driver_stats@v2:trips_today". This lets a service pin a historical FeatureView version without importing or reconstructing the underlying object. String entries are stashed at construction (no registry is available then) and resolved once, in FeatureStore.apply/plan, via a new FeatureService.resolve_pending_refs. A pinned ref always resolves from the registry snapshot for that version; an unversioned ref prefers the apply batch, then the promoted version. utils._parse_feature_ref is refactored onto a new _parse_feature_or_view_ref that makes the ':<feature>' suffix optional (whole-view refs); _parse_feature_ref is unchanged for existing callers. Signed-off-by: h-sarwat <hussein_sarwat@yahoo.com>
Offline stores re-fetch OnDemandFeatureViews from the registry independently of the version-aware online path, using an unversioned registry.list_on_demand_feature_views. A version-pinned ODFV (e.g. from a FeatureService pinning a specific ODFV version) therefore either raised "Could not find feature view from reference odfv@v1:feat" or silently served the promoted version during get_historical_features. Add a shared utils._get_requested_on_demand_feature_views that resolves each ref version-aware — pinned refs via get_feature_view_by_version (stamping projection.version_tag so name_to_use() matches downstream), unversioned refs via the promoted list as before. Route the three unversioned call sites through it: OnDemandFeatureView.get_requested_odfvs, offline_utils.get_feature_view_query_context, and dask.py's inline duplicate. This covers every offline backend, which all funnel through one of those. Unversioned refs are unchanged. Signed-off-by: h-sarwat <hussein_sarwat@yahoo.com>
Document pinning a historical feature view version inside a
FeatureService, via both string feature refs
("driver_stats@v2:trips_today") and version-pinned FeatureView objects,
on the alpha feature-view-versioning page. Clarify that
enable_online_feature_view_versioning gates both online and offline
versioned resolution (they share one code path), both in the page and in
the RegistryConfig field docstring. Update Known Limitations: offline
version-qualified retrieval and version-pinned feature services are now
supported.
Signed-off-by: h-sarwat <hussein_sarwat@yahoo.com>
There was a problem hiding this comment.
String refs introduce an unresolved lifecycle state that retrieval and serialization do not handle. A freshly constructed FeatureService(name="svc", features=["driver_stats@v2:conv_rate"]) has no projections until apply/plan. Passing that object directly to get_online_features or get_historical_features is a supported Feast pattern, but _get_features() consults the registered service while _get_feature_views_to_use() consumes the unresolved passed object, producing inconsistent resolution; to_proto() before apply also silently serializes an empty service.
Please either resolve the passed service from the registry in all retrieval paths, or reject unresolved services with a clear error. Add an integration-style test that reconstructs the string-based FeatureService in a fresh process after apply and passes that object to both online and historical retrieval.
Sorry, something went wrong.
|
I resolved the passed FeatureService from the registry in _get_feature_views_to_use when it has unresolved string refs, so it matches what _get_features already does and both retrieval paths agree instead of one seeing empty projections. Also added an integration test in test_versioning.py that reconstructs the string-ref service in a fresh store after apply and passes it to both online and historical retrieval. |
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM
Sorry, something went wrong.
There was a problem hiding this comment.
Thanks for the follow-up on the unresolved string-ref retrieval path — that looks correct.
A few remaining issues that I think should land before merge:
Inline comments have details. Would also like one integration test that actually pins v0 vs a later v1 and asserts retrieval, not only the unversioned reconstructed-service path.
Sorry, something went wrong.
| if projection.version_tag is None and fv_version: | ||
| is_latest, version_num = parse_version(fv_version) | ||
| if not is_latest: | ||
| projection.version_tag = version_num |
There was a problem hiding this comment.
This mutates the source FeatureView's own projection. FeatureView(version="v2") does not set projection.version_tag itself, so after FeatureService(features=[fv]) the caller's fv.projection.version_tag becomes 2.
Online table naming (compute_versioned_name) reads that field, so a later materialize/get on the same object can unexpectedly hit *_v2. The string-ref path already copy.copys for this reason — please copy here too before stamping version_tag.
Sorry, something went wrong.
There was a problem hiding this comment.
Copied
Sorry, something went wrong.
| for feature_service in feature_services_to_update: | ||
| # Resolve string feature refs (e.g. "driver_stats@v2") before | ||
| # inference. No-op for object-only services. | ||
| feature_service.resolve_pending_refs( |
There was a problem hiding this comment.
fvs_to_update_map only includes odfvs_to_write (write_to_online_store=True). A normal ODFV is absent, and _make_inferences runs before apply_feature_view, so the registry lookup fails too.
The docs recommend string refs, but this fails:
odfv = on_demand_feature_view(...)(src_fv)
svc = FeatureService(name="svc", features=["my_odfv"])
store.apply([src_fv, odfv, svc]) # FeatureViewNotFoundObject form features=[odfv] still works. Please pass odfvs_to_update (not just odfvs_to_write) into resolve_pending_refs.
Sorry, something went wrong.
There was a problem hiding this comment.
Built a second map, fvs_to_resolve_map, that includes the full odfvs_to_update list (all ODFVs in the apply, write-enabled or not), and passed that to resolve_pending_refs. I left infer_features on the original fvs_to_update_map so inference/online-write behavior is untouched.
Sorry, something went wrong.
| ) -> None: | ||
| """Resolve string feature refs (see ``__init__``) into projections. | ||
|
|
||
| Called automatically by ``FeatureStore.apply``/``plan`` so the pin is |
There was a problem hiding this comment.
Docstring says apply/plan resolve these refs, but prepare_for_apply does not call resolve_pending_refs, and its early return is if self._features and all(p.features for p in self.feature_view_projections).
all([]) is True, so a service with only string refs and empty projections returns immediately. to_proto() then serializes zero features.
FeatureStore.apply happens to call this first, so the happy path is OK. Direct registry.apply_feature_service(...) or any proto round-trip before apply will persist an empty service with no error.
Please reject (or resolve) unresolved _pending_feature_refs in prepare_for_apply and to_proto().
Sorry, something went wrong.
There was a problem hiding this comment.
Resolved during prepare_for_apply, raised error for to_proto
Sorry, something went wrong.
Signed-off-by: h-sarwat <hussein_sarwat@yahoo.com>
Signed-off-by: h-sarwat <hussein_sarwat@yahoo.com>
Signed-off-by: h-sarwat <hussein_sarwat@yahoo.com>
Signed-off-by: h-sarwat <hussein_sarwat@yahoo.com>
|
@ntkathole Made 4 new commits, each for the three changes you requested + the integration test. |
Sorry, something went wrong.
|
@HSarwat Please sign the commit and handle the CI failure, the object-path copy introduced a regression for schema-less FeatureViews used as a feature subset in a FeatureService |
Sorry, something went wrong.
infer_features mutated feature_grouping.projection, but __init__ now stores a decoupled copy in feature_view_projections (the serialized object). This broke schema-less FeatureViews used as a feature subset in a FeatureService. Mutate the stored projection instead. Signed-off-by: h-sarwat <hussein_sarwat@yahoo.com>
|
@ntkathole Can you check the CI now? I ran the unit and integration tests, at least the ones that I could, locally, and should be working |
Sorry, something went wrong.
…ice-version-pinning
| Back | FazBrowse Home | New Git URL |
Closes #6717.
Related to #6389 (feature versioning in offline retrieval).
What
Lets a FeatureService pin a specific historical FeatureView / OnDemandFeatureView version, honored by both get_online_features and get_historical_features. Feast's docs currently list this as a known limitation ("Feature services always resolve to the active (promoted) version"); this closes that gap.
Commits
Problem
Building a service from a version-pinned FeatureView silently falls back to the promoted version:
Two bugs cause this: FeatureService.__init__ never translates the view's version string into projection.version_tag, and utils._get_feature_views_to_use hard-codes the version as None for the FeatureService branch. A related pre-existing bug (#6389) breaks offline retrieval of version-pinned OnDemandFeatureViews: offline stores re-fetch ODFVs via an unversioned registry.list_on_demand_feature_views, so a pinned ODFV ref raises ValueError: Could not find feature view from reference ... or silently drops features across every offline backend.
Design notes for reviewers
Tests
New unit tests: test_feature_service_versioning.py (object + string-ref pinning, proto round-trip, backward compat, error guards, priority ordering) and test_odfv_offline_versioning.py (version-aware ODFV resolution, v0 fallback, non-ODFV skip, dedup). All pass; ruff (0.16.0) + mypy clean on changed files.