Skip to content

fix: Wait for Kubernetes materialization jobs when synchronous is false - #7154

Closed
patelchaitany wants to merge 1 commit into
feast-dev:masterfrom
patelchaitany:fix/k8s-async-materialization-wait
Closed

patelchaitany wants to merge 1 commit into
feast-dev:masterfrom
patelchaitany:fix/k8s-async-materialization-wait

Conversation

@patelchaitany

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

With synchronous: false, the Kubernetes compute engine created one Job for all pods and returned it right away, while the Job was still WAITING. materialize() treats any returned job that isn't ERROR as done, so it:

  • saved the materialization interval,
  • moved the feature view to AVAILABLE_ONLINE,
  • sent an OpenLineage COMPLETE event,

all before a single row reached the online store. If the pods later failed, Feast never found out. The UI and lineage still showed the run as successful.

This PR makes synchronous: false wait for the Job too, using the same _await_path_materialization loop the synchronous path already uses. synchronous now only decides how pods are grouped:

  • true: run the pods in Jobs of job_batch_size, one Job after another.
  • false: run all pods in a single Job.

Either way, the feature view is marked materialized only after the Job succeeds. The ConfigMap cleanup and the pod-log printing on failure now also run in async mode.

It also adds the update and teardown_infra methods that ComputeEngine requires. Without them, KubernetesComputeEngine(...) raised TypeError: Can't instantiate abstract class. Each run creates and deletes its own Job and ConfigMap, so there is no long-lived infrastructure, and both methods do nothing (same as the Spark application engine).

Behavior change: feast materialize with synchronous: false now blocks until the Job finishes, rather than returning right away.

Which issue(s) this PR fixes:

N/A

Checks

  • I've made sure the tests are passing.
  • My commits are signed off (git commit -s)
  • My PR title follows conventional commits format

Testing Strategy

  • Unit tests
  • Integration tests
  • Manual tests
  • Testing is not required for this change

sdk/python/tests/unit/infra/compute_engines/test_k8s_engine.py builds a real KubernetesComputeEngine with synchronous=False and a fake Job that goes WAITING → RUNNING → SUCCEEDED. It checks that one Job is created with all paths and that materialize waits until SUCCEEDED. The test fails on master (assert 0 == 2 on the poll count). It skips when the kubernetes package isn't installed.

Not tested against a real cluster.

Misc

KubernetesMaterializationJob.status() reads only conditions[0] of the Job. Newer Kubernetes versions (1.31+) can put SuccessCriteriaMet or FailureTarget first, so the wait loop might not see Complete/Failed. I haven't checked this on a real cluster, and it's out of scope here.

With synchronous=false the Kubernetes compute engine returned a job that
was still WAITING. Materialize then recorded the interval, set the feature
view to AVAILABLE_ONLINE and emitted an OpenLineage COMPLETE event before
any data was written, and pod failures were never reported.

Now both modes wait for the Job to finish. synchronous only controls
whether pods run in batches of job_batch_size or all in one Job.

Also add the update/teardown_infra hooks the ComputeEngine base class
requires, so the engine can be instantiated again. Each run creates and
cleans up its own Job and ConfigMap, so both are no-ops.

Signed-off-by: Chaitany Patel <[email protected]>
@patelchaitany
patelchaitany requested a review from a team as a code owner November 13, 2026 10:05
@codecov-commenter

codecov-commenter commented Nov 13, 2026 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.51%. Comparing base (021e9af) to head (bf92fa0).
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #7154      +/-   ##
==========================================
+ Coverage   52.32%   52.51%   +0.19%     
==========================================
  Files         459      459              
  Lines       58095    58102       +7     
  Branches     8560     8560              
==========================================
+ Hits        30397    30514     +117     
+ Misses      25614    25501     -113     
- Partials     2084     2087       +3     
Flag Coverage Δ
go-feature-server 30.96% <ø> (ø)
python-unit 54.03% <100.00%> (+0.20%) ⬆️
Files with missing lines Coverage Δ
...ast/infra/compute_engines/kubernetes/k8s_engine.py 65.24% <100.00%> (+65.24%) ⬆️

... and 1 file with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 021e9af...bf92fa0. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants