feat: Add remote materialization support via feature server#6590
feat: Add remote materialization support via feature server#6590aniketpalu wants to merge 9 commits into
Conversation
Allow store.materialize() and materialize_incremental() to delegate execution to the feature server instead of running the batch engine locally. This eliminates the need for engine-specific dependencies (PySpark, kubernetes client, etc.) and RBAC on the client pod. Components: - New shared poll_materialization_status() function - Client-side _remote_materialize() with registry-based FV state polling - POST /materialize-async and /materialize-incremental-async endpoints (202) - materialize_mode, url, timeout, poll_interval config fields - 19 unit tests + 2 E2E integration tests Addresses feast-dev#4526 (remote materialization). Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
Allow store.materialize() and materialize_incremental() to delegate execution to the feature server instead of running the batch engine locally. This eliminates the need for engine-specific dependencies (PySpark, kubernetes client, etc.) and RBAC on the client pod. Components: - Shared poll_materialization_status() with stateful FV state tracking - Client-side _remote_materialize_common() with auth forwarding - POST /materialize-async and /materialize-incremental-async (202) - _force_local guard prevents infinite recursion on server - Concurrency guard returns 409 if FV already materializing - version parameter forwarded through full chain - materialize_mode, url, timeout, poll_interval config fields Addresses feast-dev#4526 (remote materialization). Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
- Use allow_cache=False in concurrency guard to avoid stale registry reads - Close HTTP session in finally block to prevent resource leaks - Wrap remote HTTP call with descriptive error message and exception chaining - Add from-e chaining on timestamp parse errors - Improve timeout error message with actionable guidance - Add @model_validator to reject remote mode without url at config time - Add unit test for config validation Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
| materialize_mode: Literal["local", "remote"] = "local" | ||
| """When 'remote', store.materialize() delegates to the feature server's | ||
| async endpoint instead of running the batch engine locally.""" |
There was a problem hiding this comment.
I think we dont need to provide the materialize_mode config. We should strictly feature server take care of materialization delegation to compute engine. Leaving no choice to do materialization on client side.
There was a problem hiding this comment.
A cleaner approach might be: a RemoteComputeEngine (like RemoteOnlineStore/RemoteOfflineStore) that POSTs to the existing /materialize endpoint, returning a job handle with a dedicated /materialize-status/{job_id} endpoint - keeping the materialization delegation at the engine layer rather than the FeatureStore layer.
There was a problem hiding this comment.
if you mean something like
batch_engine:
type: remote.engine
path: https://feast-online:443 # same host as online
cert: /var/run/secrets/.../service-ca.crt
I thought about this before choosing current approach. I see two points which made me not take this decision.
- This adds another config section which has to indicate only one thing, i.e. trigger materialization on feature server. For this, it add 1 config section & user has to configure 2 redundant fields.
- Once client is initialized, user wont have option to try normal materialization flow if remote materialization fails for any reason.
My proposed approach is
store.materialize(remote=True, wait=False) --> pre-process check & return 202 Accepted response
store.poll_materialization() --> returns status
This approach has
- Backward compatibility - User can fall back without re-initializing client.
- Flexibility of Status polling - Full control to user to set interval of polling.
- No need of Operator changes.
- The same API can work for UI as well
apply_materialization() in SQL and Snowflake registries did not transition FeatureViewState like the file-based registry does. This caused remote materialization polling (and any state-based monitoring) to never see completion when using these registry backends. Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
- Pass online_store.cert as verify= on the materialize-async HTTP call (same server hosts both online store and materialize endpoints) - Set FV state to AVAILABLE_ONLINE in SQL/Snowflake registry apply_materialization() to match file-based registry behavior Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
Opt in with materialize(..., remote=True); URL/TLS from online_store. Add wait=False and poll_materialization(); set MATERIALIZING before 202 and reset to GENERATED on async failure; include state in FeatureView.__eq__.
Keep feast-dev#6550 batching in materialize loops; skip FV state transition when _force_local so async /materialize-async (already MATERIALIZING) works. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep feast-dev#6550 batching; skip FV state transition when _force_local so /materialize-async (already MATERIALIZING) works with SparkApplication. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep feast-dev#6550 batching; skip FV state transition when _force_local so /materialize-async (already MATERIALIZING) works with SparkApplication. Co-authored-by: Cursor <cursoragent@cursor.com>
Bring in feast-dev#6550 SparkApplication (supports_batch / _materialize_fvs_batch). Resolve feature_store.py by keeping master batch structure and threading _force_local through transition/rollback/batch helpers so async remote-mat does not double-set MATERIALIZING or wrongly roll back state. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6590 +/- ##
==========================================
- Coverage 46.00% 45.78% -0.22%
==========================================
Files 406 413 +7
Lines 48164 48974 +810
Branches 6814 6950 +136
==========================================
+ Hits 22157 22425 +268
- Misses 24461 25000 +539
- Partials 1546 1549 +3
... and 10 files with indirect coverage changes Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
Refresh with current feast-dev#6590 tip (includes master merge with feast-dev#6550). Keep spark_application Dockerfile postgres extra for E2E. Co-authored-by: Cursor <cursoragent@cursor.com>
What this PR does / why we need it:
Allow store.materialize() and materialize_incremental() to delegate execution to the feature server instead of running the batch engine locally. This eliminates the need for engine-specific dependencies (PySpark, kubernetes client, etc.) and RBAC on the client pod. Components:
Which issue(s) this PR fixes:
Checks
git commit -s)Testing Strategy
Misc