Commit dcd496f
authored
feat: Bring Your Own Spark - SparkApplication (#6550)
* feat: Add SparkApplicationComputeEngine for Kubernetes-native batch materialization
Adds a new batch compute engine that submits materialization jobs as
SparkApplication CRDs via the Kubeflow Spark Operator. One 'feast materialize'
call creates one SparkApplication pod that processes all feature views using
distributed Spark, rather than running in-process on the Feast server.
Key changes:
- Refactor materialize()/materialize_incremental() to pass all tasks to the
engine in a single batch call instead of looping per feature view. Existing
engines are unaffected (base class loops tasks internally via _materialize_one).
- Add public get_provider() method on FeatureStore.
- New spark_application engine: config, compute, job, driver script, Dockerfile.
- 12 unit tests covering config, validation, CR structure, state mapping,
timeout, cleanup, and job naming.
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
* feat: Add per-FV result reporting and clean up Dockerfile
- Pod calls apply_materialization via gRPC after each successful FV,
setting state to AVAILABLE_ONLINE. Server reads FV state post-completion
to determine per-FV success/failure in batched SparkApplication runs.
- registry_address is now mandatory (simplified from complex path heuristic).
- Dockerfile rewritten to install feast from source (matches K8s engine pattern).
- Unit tests updated: 15/15 pass (3 new tests for _build_per_fv_jobs).
- E2E validated: 5 FVs x 9600 rows, 5 executors, all AVAILABLE_ONLINE.
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
* Minor lint & formatting change
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
* feat: Switch to ConfigMap, remove registry_address, reject file-based stores
- Config delivery: Secret → ConfigMap. Operator's ClusterRole already has
full ConfigMap CRUD — avoids widening RBAC for Secrets in ODH.
Matches KubernetesComputeEngine pattern.
- Removed registry_address config field. Pod inherits server's registry
config (SQL, Snowflake) directly and writes apply_materialization()
to the same database. Eliminates TLS certificate mounting complexity.
- Reject file-based offline stores (dask, file, duckdb) and registries
(file) at __init__(), same as existing sqlite/faiss online store
rejection. SparkApplication pod has ephemeral filesystem.
- Dockerfile: added PYTHONPATH/SPARK_HOME for PySpark, added pymysql.
- 20/20 unit tests pass.
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
* Minor formatting
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
* fix: address PR #6550 review — retry, validation, per-FV status
- Remove redundant get_provider(); callers use .provider property
- Replace SparkSession monkey-patch with per-thread session binding
- Smart retry: only 5xx/429; fail fast on 401/403 with RBAC hint
- Retry ConfigMap + SparkApplication creation (transient K8s errors)
- Validate env entries: require name + value or valueFrom (K8s EnvVar)
- Independent per-FV job status via CompletedMaterializationJob
- Exit 1 on any FV failure so SparkApp CR reflects partial failure
- Cleanup logs include kubectl delete command for manual recovery
- Lint: pragma allowlist on test fixture URL
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
* fix: isolate batch materialization to supports_batch engines
Restore master's per-FV materialize path for engines that do not
support batching; keep SparkApplication on the existing batch path
via ComputeEngine.supports_batch.
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
* fix: address ntkathole review — dates dataclass, jobs check, UNKNOWN, cleanup
Replace __end_date__ sentinel with _MaterializationDateRange; fail fast
if engine job count mismatches; map UNKNOWN SparkApp state to WAITING;
always cleanup ConfigMap/CR after wait.
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
* fix: lazy-init K8s client for spark_application engine
Defer kubeconfig load until materialize/cleanup so feast apply can
construct the engine without a cluster.
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
* chore: Refresh pixi.lock after pyproject.toml dependency changes
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
* fix: skip duplicate apply_materialization for SparkApplication
Pod already writes watermarks via applies_materialization; server
batch path skips the second call to avoid duplicate intervals.
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
* fix: harden supports_batch check against missing batch_engine
Use null-safe getattr so materialize falls back to the per-FV path
when batch_engine or supports_batch is absent.
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>
---------
Signed-off-by: Aniket Paluskar <apaluska@redhat.com>1 parent 14e0a83 commit dcd496f
12 files changed
Lines changed: 1822 additions & 168 deletions
File tree
- sdk/python
- feast
- infra/compute_engines
- spark_application
- tests/unit/infra/compute_engines
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
85 | 85 | | |
86 | 86 | | |
87 | 87 | | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
88 | 103 | | |
89 | 104 | | |
90 | 105 | | |
| |||
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
Lines changed: 34 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
Whitespace-only changes.
0 commit comments