← 输入框|github.com|刷新
Skip to content

feat: Add optional GLIDE client for Redis online reads - #6870

Merged
ntkathole merged 2 commits into
feast-dev:masterfrom
chandlerok:feat/redis-glide-client
Oct 1, 2026
Merged

ntkathole merged 2 commits into
feast-dev:masterfrom
chandlerok:feat/redis-glide-client

Conversation

@chandlerok

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

Adds an opt-in GLIDE-backed Redis online read path for Python get_online_features.

The existing redis-py path does command packing, socket parsing, and response handling in Python. Under thread contention, that work repeatedly reacquires the GIL and can make online reads much slower than single-threaded benchmarks suggest.

This PR adds a client: glide option to the Redis online store config. When enabled, Feast uses GLIDE for the batched Redis read while preserving the existing Redis storage layout and default redis-py behavior.

This PR intentionally does not include the HGETALL threshold optimization. That can be evaluated separately.

Scope

  • RedisOnlineStoreConfig gains client: redis | glide, defaulting to redis.
  • Only the synchronous read paths change (online_read and the batched per-feature-view read behind get_online_features). Writes and get_online_features_async keep using redis-py.
  • GLIDE reads the same entity keys (serialize_entity_key + project) and the same hashed field names (_mmh3(f"{fv}:{name}") plus _ts:<fv>) that Feast already writes, so existing data needs no migration.
  • connection_string support: host/port, db, password, username, ssl, socket_timeout, socket_connect_timeout. Unknown parameters are logged and ignored. Sentinel is rejected with a clear error because GLIDE has no Sentinel support.
  • valkey-glide-sync>=2.5,<3 is a new optional extra, feast[glide]. It is imported lazily so users who never opt in are unaffected. Configuring client: glide without it raises FeastExtrasDependencyImportError naming the extra.

Implementation notes

The read client is selected in one place, RedisOnlineStore._read_hash_fields, which takes a list of (key, fields) HMGET commands and returns one reply per command. Both clients produce the same ordering, so the existing response conversion (_convert_redis_values_to_protobuf) and timestamp handling are untouched.

_glide_hmget_batch builds a single Batch(is_atomic=False) (or ClusterBatch(is_atomic=False) for cluster) and calls exec(batch, raise_on_error=True) once, so the whole fetch is one FFI call.

Three type annotations were corrected because the GLIDE path made the existing inaccuracy visible: _generate_hset_keys_for_features returns hashed bytes keys, not str, and the value sequences accepted by _convert_redis_values_to_protobuf / _get_features_for_entity legitimately contain None for missing fields.

Which issue(s) this PR fixes:

Related to #6856.

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

Commands run:

# Unit tests
uv run python -m pytest sdk/python/tests/unit/infra/online_store/test_redis.py -q
# 35 passed

# Redis-related unit tests together
uv run python -m pytest sdk/python/tests/unit/infra/online_store/test_redis.py \
    sdk/python/tests/unit/infra/online_store/test_redis_versioning.py \
    sdk/python/tests/unit/infra/online_store/test_helpers.py -q
# 65 passed

# Integration tests
uv run python -m pytest --integration \
    sdk/python/tests/integration/online_store/test_redis_glide_client.py -q
# 2 passed

# Lint and format
uv run ruff check <changed files>            # All checks passed!
uv run ruff format --check <changed files>   # 3 files already formatted

# Types
uv run bash -c "cd sdk/python && mypy feast/infra/online_stores/redis.py"
# Success: no issues found in 1 source file

Notes on the test runs

  • The integration test seeds rows with the default redis-py client, then reads them back with client: redis and client: glide and asserts the results are byte-identical, both for online_read and for the batched _read_features_per_fv response (including a missing entity). If GLIDE used different keys or field names it would read NOT_FOUND instead of matching.
  • I ran the integration test against a live Valkey 9 on localhost:6379 because the Docker daemon on my machine could not create containers (error creating temporary lease: read-only file system). The committed test uses testcontainers with redis:7, matching the existing test_redis_versioning.py, and is skipped when Docker is unavailable.
  • glide is added to the ci extra in pyproject.toml, but the pinned lock files (sdk/python/requirements/py*-ci-requirements.txt) need a make lock-python-dependencies-all run before CI installs it. Until then the tests that need the real package skip via importorskip; the mock-based tests, including the missing-dependency error test, still run.
  • mypy on feast/infra/online_stores/redis.py is clean. test_redis.py already had 19 mypy errors at master (unrelated pre-existing assertions on Optional dicts and list invariance in online_write_batch test data); this branch reduces that to 16 and adds none. I left those pre-existing errors alone to keep this diff focused.

Misc

The GLIDE batch is non-atomic by design, matching the existing pipeline(transaction=False) behavior. valkey-glide-sync 2.5.0 and 2.5.3 were both checked to confirm the Batch/ClusterBatch/config signatures used here exist across the 2.5 line.

I am happy to add glide to the ci lock files in this PR if you would rather have CI coverage of the GLIDE path immediately.

@chandlerok
chandlerok marked this pull request as ready for review September 25, 2026 15:29
@chandlerok
chandlerok requested a review from a team as a code owner September 25, 2026 15:29
@chandlerok

Copy link
Copy Markdown
Contributor Author

@patelchaitany would you mind reviewing this when you have a chance? It is the valkey-glide half of #6856 on its own; the HGETALL threshold change is deliberately left out.

(Posting this as a comment because the review-request API requires write access to this repo, which a fork author does not have.)

@chandlerok
chandlerok marked this pull request as draft September 25, 2026 15:38
@chandlerok

Copy link
Copy Markdown
Contributor Author

@ntkathole tagging you as the right reviewer for this one: it extends the Redis online store read path from #6337, and you have merged most of the recent Redis online store changes (#6446, #6656).

Scope: an opt-in client: glide on RedisOnlineStoreConfig that runs the batched HMGET as a single non-atomic valkey-glide batch, so the fetch runs off the GIL. redis-py stays the default; writes and async reads are unchanged; the HGETALL threshold change is deliberately not included.

@chandlerok
chandlerok marked this pull request as ready for review September 25, 2026 20:38
@codecov-commenter

codecov-commenter commented Sep 26, 2026 •

Copy link
Copy Markdown

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

Codecov Report

❌ Patch coverage is 58.90411% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 48.62%. Comparing base (81673d9) to head (6dd260a).

Files with missing lines Patch % Lines
sdk/python/feast/infra/online_stores/redis.py 58.90% 30 Missing ⚠️
❗ 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    #6870      +/-   ##
==========================================
+ Coverage   48.58%   48.62%   +0.03%     
==========================================
  Files         427      427              
  Lines       53787    53845      +58     
  Branches     7834     7844      +10     
==========================================
+ Hits        26132    26181      +49     
- Misses      25788    25797       +9     
  Partials     1867     1867              
Flag Coverage Δ
go-feature-server 30.58% <ø> (ø)
python-unit 49.99% <58.90%> (+0.04%) ⬆️
Files with missing lines Coverage Δ
sdk/python/feast/infra/online_stores/redis.py 60.87% <58.90%> (+3.12%) ⬆️

... 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 81673d9...6dd260a. 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.

@ntkathole ntkathole left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the well-structured PR! Left a couple of suggestions below.

# Only set when `client: glide` is configured, so the native extension stays
# untouched for users who never opt in.
_glide_client: Optional[Any] = None

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: _glide_client is cached here but never cleaned up. The existing teardown() closes the redis-py client — the GLIDE client should get the same treatment to release native (Rust-side) resources, file descriptors, and the connection pool.

Something like:

def teardown(self, config, tables, entities):
    ...
    if self._glide_client:
        self._glide_client.close()
        self._glide_client = None

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in d12d035. teardown() now closes self._glide_client and sets it back to None, so the native client is released as you suggested.

One note: the redis-py client was not actually being closed in teardown() before this change either (the method only deletes keys), so I scoped this to the GLIDE client rather than also changing the redis-py lifecycle in this PR. Happy to close that one too if you'd prefer it here.


if online_store_config.client == RedisClient.glide:
glide_sync = _load_glide_sync()
return _glide_hmget_batch(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_load_glide_sync() is called on every read when client == RedisClient.glide. While Python caches imported modules in sys.modules, this still incurs a function-call + dict-lookup overhead per read that is easy to avoid.

Consider caching the module reference on the instance alongside _glide_client, e.g.:

_glide_sync: Optional[Any] = None

def _get_glide_sync(self):
    if self._glide_sync is None:
        self._glide_sync = _load_glide_sync()
    return self._glide_sync

Then _read_hash_fields and _get_glide_client can both use self._get_glide_sync() instead of calling _load_glide_sync() each time.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in d12d035. Added _get_glide_sync(), which imports the module once and caches it on the instance; both _read_hash_fields and _get_glide_client now go through it instead of calling _load_glide_sync() each read.

@ntkathole

Copy link
Copy Markdown
Member

Also, please fix the linting error in CI

@chandlerok

Copy link
Copy Markdown
Contributor Author

Updated in d12d035. Both review suggestions are addressed and the lint failure is fixed:

  • teardown() closes the GLIDE client and clears the cached reference, releasing the native client.
  • glide_sync is cached per store via _get_glide_sync(), so reads no longer re-lookup the module.
  • lint-python fix: the failure was a detect-secrets false positive on the hunter2 test literals in test_redis.py, now allowlisted with # pragma: allowlist secret.

Testing (local, against a real Valkey 9.1.2 on 127.0.0.1:6379)

The Docker daemon here can't create containers (permission denied on the socket), so the testcontainers-based integration test was run against the local Valkey instead:

  • pytest test_redis.py test_redis_versioning.py test_helpers.py → 68 passed (3 new tests: module caching, teardown close, teardown no-op).
  • The two committed integration tests (test_glide_online_read_matches_redis_py, test_glide_batched_read_matches_redis_py) run against the local Valkey → 2 passed.
  • Full FeatureStore.get_online_features e2e with client: glide: apply a real repo, seed via redis-py, read through the public API → results identical to client: redis, including the missing entity.
  • Real-client lifecycle e2e: teardown() closes the actual GlideClient, a subsequent read recreates it and still returns correct values.
  • ruff check / ruff format --check clean; mypy feast/infra/online_stores/redis.py clean with the CI-pinned mypy==1.11.2 and types-protobuf==3.19.22.

The checks on this fork PR show action_required, so they need a maintainer to approve before the workflows actually run.

@chandlerok
chandlerok force-pushed the feat/redis-glide-client branch from d12d035 to 93c88d2 Compare September 30, 2026 21:34
@chandlerok

Copy link
Copy Markdown
Contributor Author

Correction: the head is now 93c88d2 (same tree as d12d035). That commit only changes the author/committer metadata — the first push reset the author name to chandlerok while the sign-off line said Chandler King, which tripped DCO. Re-authored so the sign-off matches, DCO is green again. No code change.

@ntkathole
ntkathole force-pushed the feat/redis-glide-client branch from 93c88d2 to b888c99 Compare October 1, 2026 13:13
Adds a `client: glide` option to RedisOnlineStoreConfig. When set, the
synchronous read paths (online_read and the batched read behind
get_online_features) issue their HMGET commands as one non-atomic GLIDE
batch, so the fetch runs off the GIL instead of in Python per command.

Default behavior is unchanged: redis-py remains the default client, all
writes and async reads keep using redis-py, and GLIDE reads the same
entity keys and hashed feature fields Feast already writes.

valkey-glide-sync is an optional dependency behind the new `feast[glide]`
extra. Configuring `client: glide` without it installed raises a Feast
extras import error naming the extra to install.

This does not include the HGETALL threshold change from the same issue.

Related to feast-dev#6856.

Signed-off-by: Chandler King <chandleroking@gmail.com>
Addresses review feedback on the GLIDE read path:

- teardown() now closes the native GLIDE client and clears the cached
  reference, so its Rust-side resources and file descriptors are released.
- The glide_sync module is imported once per store and cached on the
  instance instead of being looked up on every read.
- Allowlist the test password literals so detect-secrets stops failing
  lint-python.

Signed-off-by: Chandler King <chandleroking@gmail.com>
@ntkathole
ntkathole force-pushed the feat/redis-glide-client branch from b888c99 to 6dd260a Compare October 1, 2026 14:11
@chandlerok

Copy link
Copy Markdown
Contributor Author

@ntkathole would you mind taking another look when you have a chance?

Both of your suggestions from Sep 26 are addressed:

  • teardown() closes the GLIDE client and clears the cached reference, so a store that is torn down and re-created does not reuse a dead connection.
  • The lint failure CI flagged is fixed.

This is still the valkey-glide half of #6856 on its own; the HGETALL threshold change is deliberately not in here. Happy to split or drop anything if you would rather it landed differently.

@chandlerok

Copy link
Copy Markdown
Contributor Author

oh nvm I see you already reviewed! ty!

@ntkathole
ntkathole merged commit 6e9a532 into feast-dev:master Oct 1, 2026
24 of 26 checks passed
ntkathole pushed a commit that referenced this pull request Oct 13, 2026
# [0.67.0](v0.66.0...v0.67.0) (2026-10-13)

### Bug Fixes

* Allow dill 0.4 so UDF serialization works on Python 3.14 ([#6858](#6858)) ([139704f](139704f))
* Allow serving features while a feature view is MATERIALIZING ([#6789](#6789)) ([e2d7fe2](e2d7fe2)), closes [#6780](#6780)
* Allowlist the pinned commit SHA flagged by detect-secrets ([4b81d18](4b81d18))
* Apply point-in-time filter correctly with the Polars backend ([#6992](#6992)) ([01224d0](01224d0))
* Authorize registry server writes before deserializing UDFs ([e0ef16e](e0ef16e))
* Automate versioned documentation publication ([#6763](#6763)) ([5ad5592](5ad5592)), closes [#6762](#6762)
* Avoid NumPy generic-unit deprecation when importing feast.type_map ([5fea698](5fea698))
* Bind metrics, REST registry, ui, and lineage servers dual-stack ([#6886](#6886)) ([8d2773c](8d2773c))
* Bound Arrow Flight batch size in the offline server ([#6896](#6896)) ([d169238](d169238))
* Compute std and var correctly for tiled aggregations ([213a130](213a130))
* Convert PdfBytes values to protos like ImageBytes ([#6968](#6968)) ([af20fe4](af20fe4))
* Decode fixed_size_list as the matching Feast list value type ([#6944](#6944)) ([8cfe891](8cfe891))
* Do not log /metrics requests from the pre-fork metrics server thread ([7087f1f](7087f1f)), closes [#6928](#6928)
* Don't return from finally blocks in REST registry helpers ([d7cb4d0](d7cb4d0))
* Encode non-finite floats in feature server JSON responses ([#6930](#6930)) ([211ecb8](211ecb8))
* Feature freshness logic updated ([#6765](#6765)) ([f0bc070](f0bc070))
* Fix monitoring auth ([015cc84](015cc84))
* Handle non-nanosecond timestamps in tiled aggregations ([b8989cb](b8989cb))
* Improve feature list column sizing ([#6793](#6793)) ([2573693](2573693))
* Include vector attributes in Field equality ([#6934](#6934)) ([298c3f6](298c3f6))
* Increase feast container probe timeouts to avoid false restarts ([e8dbd50](e8dbd50))
* Infer the tensor type from retrieved values in to_tensor ([a03e323](a03e323))
* Infer timestamps for datetime columns in any unit or timezone ([810391f](810391f))
* Infer vector width when vector_length is undeclared ([0056565](0056565)), closes [#6907](#6907)
* Initialize auth managers in standalone lineage server ([#6873](#6873)) ([ecd0d38](ecd0d38))
* Keep a zero watermark delay threshold on a Kafka source ([e2e28c7](e2e28c7))
* Keep entity rows apart in the ibis point-in-time join ([a87c070](a87c070))
* Keep the BatchFeatureView type and settings when copying it ([#6989](#6989)) ([013fc57](013fc57))
* Keep tiling, offline and stream engine settings when copying a StreamFeatureView ([fac0f88](fac0f88))
* Limit tiled max and min aggregations to the window ([2583c45](2583c45))
* Load Milvus collections once instead of on every query ([#6882](#6882)) ([f9e91fa](f9e91fa))
* Make vector length validation reachable, schema-driven and vectorized ([#6909](#6909)) ([29af8c0](29af8c0)), closes [#6907](#6907)
* Map INT32_LIST, PDF_BYTES and IMAGE_BYTES type names to their ValueType ([8c1e825](8c1e825))
* Map narrow and unsigned Arrow integer types to Feast value types ([#6960](#6960)) ([ae74360](ae74360))
* Map Spark smallint and tinyint columns to INT32 ([9d42729](9d42729))
* Map SQL Server bigint to INT64 and float to DOUBLE ([6d15533](6d15533))
* Map Trino DECIMAL columns to pyarrow decimal128 ([155bc24](155bc24))
* Normalize Arrow-backed dtypes from Ray Dataset.to_pandas() for pyarrow >=25 compatibility ([#6916](#6916)) ([374f1d7](374f1d7))
* **operator:** Set grpc appProtocol on the offline Service port ([f9dcfb5](f9dcfb5))
* Pin expected tensor to same device in online retrieval test ([#6777](#6777)) ([1f2584d](1f2584d))
* Preserve an unset aggregation time window across a proto round-trip ([2000379](2000379))
* Preserve entity row order in precomputed reads ([ce37029](ce37029))
* Pull the MinIO test image from pgsty/minio ([fe27230](fe27230))
* Pull the MinIO test image from quay ([#6838](#6838)) ([367001b](367001b))
* Raise Trino monitoring query errors other than a missing table ([6161766](6161766))
* Read Kafka and Kinesis sources without a batch source from proto ([a620f5c](a620f5c))
* Read naive datetimes as UTC in UnixTimestamp values ([bc703d9](bc703d9))
* Record which storage class wrote a custom_storage payload ([#6988](#6988)) ([c0545f7](c0545f7))
* Refresh the SQL registry cache after deleting a data source ([66c55e3](66c55e3))
* Refresh the SQL registry cache after deleting a permission ([6b212f5](6b212f5))
* Reject unknown resource types and actions in the REST permission API ([a5eaa36](a5eaa36))
* Remove pip install command from Redis GLIDE docstring ([66ff990](66ff990))
* Remove runtime pip install hints from mlflow errors ([dd9f099](dd9f099))
* Remove unsupported vector_len from PostgreSQL tutorial config ([fcc9a85](fcc9a85))
* Repair Chronon operator validation and Pixi CI setup ([#6947](#6947)) ([3710f78](3710f78))
* Report Dask monitoring read errors instead of no data ([81673d9](81673d9))
* Resolve feature view batch source name against registry ([f8883d0](f8883d0))
* Restrict UI server CORS to trusted origins ([#6986](#6986)) ([5e7ef3e](5e7ef3e))
* Return feature_view_metadata from the REST feature server ([#6927](#6927)) ([bc5aeef](bc5aeef))
* Serve aliased on demand feature views in feature services ([823b92e](823b92e))
* Snapshot tag filters in registry cache keys ([81e1546](81e1546))
* Stabilize materialization checks across hour boundaries ([#6948](#6948)) ([acadb17](acadb17))
* Stop the Couchbase online store reporting failed writes as written ([b3f3c98](b3f3c98))
* Support SQL registry dump ([b60f9c7](b60f9c7))
* Treat datetimes with a None utcoffset as naive ([687bee8](687bee8))
* Unwrap SecretStr tokens when building Trino auth objects ([#6771](#6771)) ([922db5c](922db5c))
* Use a valid ShuffleStrategy for the Ray DatasetContext ([6259f5c](6259f5c))
* Use do_exchange for offline server reads to support HPA ([bae07fc](bae07fc))
* Use group_by in Polars backend aggregation ([#6965](#6965)) ([7b9fad2](7b9fad2))
* Use upstream kubectl image as feast-operator CronJob default ([d6cc1dc](d6cc1dc))
* Use UTC end bound and correct docs for disable_event_timestamp ([#6956](#6956)) ([cc07c82](cc07c82)), closes [#6936](#6936)

### Features

* Add a non-JVM read path for Lance data sources ([#6943](#6943)) ([e2a53bb](e2a53bb)), closes [#6925](#6925) [#5782](#5782) [#6909](#6909)
* Add a non-JVM write path for Lance data sources ([#6945](#6945)) ([f754323](f754323)), closes [#6943](#6943) [#6909](#6909)
* Add Chronon online and offline store integrations ([#6188](#6188)) ([dd059c6](dd059c6))
* Add consistency_level to the Milvus online store config ([97296c1](97296c1))
* Add dualStack server option to the Feast operator ([#6887](#6887)) ([725a147](725a147)), closes [#6977](#6977)
* Add Lance optional dependencies ([#6958](#6958)) ([20bc993](20bc993))
* Add LanceFormat table format with version/tag pinning ([1196e22](1196e22)), closes [#5650](#5650)
* Add MLflow as a first-class offline DataSource for Feast ([#6702](#6702)) ([3667772](3667772))
* Add optional GLIDE client for Redis online reads ([#6870](#6870)) ([6e9a532](6e9a532))
* Add quality monitoring features for Trino offline store ([#6779](#6779)) ([9340545](9340545))
* Add SavedDatasetLanceStorage ([1118d3e](1118d3e))
* Add standalone MCP server as a first-class component ([0efab5c](0efab5c)), closes [python-keycloak#623](https://github.com/python-keycloak/issues/623)
* Add structured audit logging for MCP feature server ([#6456](#6456)) ([640ac70](640ac70))
* Add Trino compute engine for batch retrieval and materialization ([#6898](#6898)) ([11a47b4](11a47b4))
* Batch Postgres online reads across feature views ([#6832](#6832)) ([514bee7](514bee7)), closes [#3259](#3259)
* **bigtable:** Make write batch size and concurrency configurable ([#6847](#6847)) ([5388522](5388522))
* Bucket feature count labels in latency metrics ([#6811](#6811)) ([d9ea120](d9ea120))
* Expose runtime version in Feast UI ([#6843](#6843)) ([fa8f06b](fa8f06b))
* Make Milvus index and search params configurable ([ef743ff](ef743ff))
* Offline write batch for IcebergSource ([5be5ed0](5be5ed0))
* OpenLineage consumer improvements - dataset versioning, column lineage, ownership ([69f294e](69f294e))
* **operator:** Add tolerations and nodeSelector to the FeatureStore CR ([#6741](#6741)) ([03dac6f](03dac6f))
* Serve the MCP server dual-stack on --host :: ([4fc9726](4fc9726))
* Support Milvus partition keys in the Milvus online store ([0ed3285](0ed3285))
* Support token, uri and db_name in the Milvus online store ([c5efecd](c5efecd))
* Version-pinning for FeatureService (online + offline) ([#6718](#6718)) ([787845a](787845a))

### Performance Improvements

* Avoid pandas copy in Spark reads ([#6878](#6878)) ([4771156](4771156))
* Decouple metrics HTTP server into a dedicated child process ([#6855](#6855)) ([0b621de](0b621de))
* Reduce online serving hot-path overhead from metrics and audit logging ([5ee7ee3](5ee7ee3))
ntkathole added a commit to opendatahub-io/feast that referenced this pull request Oct 14, 2026
* fix: Increase feast container probe timeouts to avoid false restarts

Signed-off-by: Srihari <svenkata@redhat.com>

* chore: Remove unused hermeto offline tree and sdist requirement locks (feast-dev#6987)

* chore: Remove unused multicloud hermeto offline build tree

Drop sdk/python/feast/infra/feature_servers/multicloud/offline/, which only
supported local hermeto/arrow-from-source and RPM lock offline image builds
and is unused by Makefile CI, GitHub Actions, or the standard feature-server
Dockerfiles. Also clear related .secrets.baseline entries.

Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: Drop unused minimal-sdist requirement locks

Remove py3.10–3.12 minimal-sdist(-build) lockfiles, stop generating them
in lock-python-dependencies-all, and delete the minimal-sdist-build extra.
They only supported hermeto build-from-sdist offline image builds.

Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: Refresh pixi.lock after removing minimal-sdist-build

Keep pixi install --locked in sync with the pyproject.toml optional
dependency change so ray/duckdb CI environments can install.

Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(release): release 0.67.0

# [0.67.0](feast-dev/feast@v0.66.0...v0.67.0) (2026-10-13)

### Bug Fixes

* Allow dill 0.4 so UDF serialization works on Python 3.14 ([feast-dev#6858](feast-dev#6858)) ([139704f](feast-dev@139704f))
* Allow serving features while a feature view is MATERIALIZING ([feast-dev#6789](feast-dev#6789)) ([e2d7fe2](feast-dev@e2d7fe2)), closes [feast-dev#6780](feast-dev#6780)
* Allowlist the pinned commit SHA flagged by detect-secrets ([4b81d18](feast-dev@4b81d18))
* Apply point-in-time filter correctly with the Polars backend ([feast-dev#6992](feast-dev#6992)) ([01224d0](feast-dev@01224d0))
* Authorize registry server writes before deserializing UDFs ([e0ef16e](feast-dev@e0ef16e))
* Automate versioned documentation publication ([feast-dev#6763](feast-dev#6763)) ([5ad5592](feast-dev@5ad5592)), closes [feast-dev#6762](feast-dev#6762)
* Avoid NumPy generic-unit deprecation when importing feast.type_map ([5fea698](feast-dev@5fea698))
* Bind metrics, REST registry, ui, and lineage servers dual-stack ([feast-dev#6886](feast-dev#6886)) ([8d2773c](feast-dev@8d2773c))
* Bound Arrow Flight batch size in the offline server ([feast-dev#6896](feast-dev#6896)) ([d169238](feast-dev@d169238))
* Compute std and var correctly for tiled aggregations ([213a130](feast-dev@213a130))
* Convert PdfBytes values to protos like ImageBytes ([feast-dev#6968](feast-dev#6968)) ([af20fe4](feast-dev@af20fe4))
* Decode fixed_size_list as the matching Feast list value type ([feast-dev#6944](feast-dev#6944)) ([8cfe891](feast-dev@8cfe891))
* Do not log /metrics requests from the pre-fork metrics server thread ([7087f1f](feast-dev@7087f1f)), closes [feast-dev#6928](feast-dev#6928)
* Don't return from finally blocks in REST registry helpers ([d7cb4d0](feast-dev@d7cb4d0))
* Encode non-finite floats in feature server JSON responses ([feast-dev#6930](feast-dev#6930)) ([211ecb8](feast-dev@211ecb8))
* Feature freshness logic updated ([feast-dev#6765](feast-dev#6765)) ([f0bc070](feast-dev@f0bc070))
* Fix monitoring auth ([015cc84](feast-dev@015cc84))
* Handle non-nanosecond timestamps in tiled aggregations ([b8989cb](feast-dev@b8989cb))
* Improve feature list column sizing ([feast-dev#6793](feast-dev#6793)) ([2573693](feast-dev@2573693))
* Include vector attributes in Field equality ([feast-dev#6934](feast-dev#6934)) ([298c3f6](feast-dev@298c3f6))
* Increase feast container probe timeouts to avoid false restarts ([e8dbd50](feast-dev@e8dbd50))
* Infer the tensor type from retrieved values in to_tensor ([a03e323](feast-dev@a03e323))
* Infer timestamps for datetime columns in any unit or timezone ([810391f](feast-dev@810391f))
* Infer vector width when vector_length is undeclared ([0056565](feast-dev@0056565)), closes [feast-dev#6907](feast-dev#6907)
* Initialize auth managers in standalone lineage server ([feast-dev#6873](feast-dev#6873)) ([ecd0d38](feast-dev@ecd0d38))
* Keep a zero watermark delay threshold on a Kafka source ([e2e28c7](feast-dev@e2e28c7))
* Keep entity rows apart in the ibis point-in-time join ([a87c070](feast-dev@a87c070))
* Keep the BatchFeatureView type and settings when copying it ([feast-dev#6989](feast-dev#6989)) ([013fc57](feast-dev@013fc57))
* Keep tiling, offline and stream engine settings when copying a StreamFeatureView ([fac0f88](feast-dev@fac0f88))
* Limit tiled max and min aggregations to the window ([2583c45](feast-dev@2583c45))
* Load Milvus collections once instead of on every query ([feast-dev#6882](feast-dev#6882)) ([f9e91fa](feast-dev@f9e91fa))
* Make vector length validation reachable, schema-driven and vectorized ([feast-dev#6909](feast-dev#6909)) ([29af8c0](feast-dev@29af8c0)), closes [feast-dev#6907](feast-dev#6907)
* Map INT32_LIST, PDF_BYTES and IMAGE_BYTES type names to their ValueType ([8c1e825](feast-dev@8c1e825))
* Map narrow and unsigned Arrow integer types to Feast value types ([feast-dev#6960](feast-dev#6960)) ([ae74360](feast-dev@ae74360))
* Map Spark smallint and tinyint columns to INT32 ([9d42729](feast-dev@9d42729))
* Map SQL Server bigint to INT64 and float to DOUBLE ([6d15533](feast-dev@6d15533))
* Map Trino DECIMAL columns to pyarrow decimal128 ([155bc24](feast-dev@155bc24))
* Normalize Arrow-backed dtypes from Ray Dataset.to_pandas() for pyarrow >=25 compatibility ([feast-dev#6916](feast-dev#6916)) ([374f1d7](feast-dev@374f1d7))
* **operator:** Set grpc appProtocol on the offline Service port ([f9dcfb5](feast-dev@f9dcfb5))
* Pin expected tensor to same device in online retrieval test ([feast-dev#6777](feast-dev#6777)) ([1f2584d](feast-dev@1f2584d))
* Preserve an unset aggregation time window across a proto round-trip ([2000379](feast-dev@2000379))
* Preserve entity row order in precomputed reads ([ce37029](feast-dev@ce37029))
* Pull the MinIO test image from pgsty/minio ([fe27230](feast-dev@fe27230))
* Pull the MinIO test image from quay ([feast-dev#6838](feast-dev#6838)) ([367001b](feast-dev@367001b))
* Raise Trino monitoring query errors other than a missing table ([6161766](feast-dev@6161766))
* Read Kafka and Kinesis sources without a batch source from proto ([a620f5c](feast-dev@a620f5c))
* Read naive datetimes as UTC in UnixTimestamp values ([bc703d9](feast-dev@bc703d9))
* Record which storage class wrote a custom_storage payload ([feast-dev#6988](feast-dev#6988)) ([c0545f7](feast-dev@c0545f7))
* Refresh the SQL registry cache after deleting a data source ([66c55e3](feast-dev@66c55e3))
* Refresh the SQL registry cache after deleting a permission ([6b212f5](feast-dev@6b212f5))
* Reject unknown resource types and actions in the REST permission API ([a5eaa36](feast-dev@a5eaa36))
* Remove pip install command from Redis GLIDE docstring ([66ff990](feast-dev@66ff990))
* Remove runtime pip install hints from mlflow errors ([dd9f099](feast-dev@dd9f099))
* Remove unsupported vector_len from PostgreSQL tutorial config ([fcc9a85](feast-dev@fcc9a85))
* Repair Chronon operator validation and Pixi CI setup ([feast-dev#6947](feast-dev#6947)) ([3710f78](feast-dev@3710f78))
* Report Dask monitoring read errors instead of no data ([81673d9](feast-dev@81673d9))
* Resolve feature view batch source name against registry ([f8883d0](feast-dev@f8883d0))
* Restrict UI server CORS to trusted origins ([feast-dev#6986](feast-dev#6986)) ([5e7ef3e](feast-dev@5e7ef3e))
* Return feature_view_metadata from the REST feature server ([feast-dev#6927](feast-dev#6927)) ([bc5aeef](feast-dev@bc5aeef))
* Serve aliased on demand feature views in feature services ([823b92e](feast-dev@823b92e))
* Snapshot tag filters in registry cache keys ([81e1546](feast-dev@81e1546))
* Stabilize materialization checks across hour boundaries ([feast-dev#6948](feast-dev#6948)) ([acadb17](feast-dev@acadb17))
* Stop the Couchbase online store reporting failed writes as written ([b3f3c98](feast-dev@b3f3c98))
* Support SQL registry dump ([b60f9c7](feast-dev@b60f9c7))
* Treat datetimes with a None utcoffset as naive ([687bee8](feast-dev@687bee8))
* Unwrap SecretStr tokens when building Trino auth objects ([feast-dev#6771](feast-dev#6771)) ([922db5c](feast-dev@922db5c))
* Use a valid ShuffleStrategy for the Ray DatasetContext ([6259f5c](feast-dev@6259f5c))
* Use do_exchange for offline server reads to support HPA ([bae07fc](feast-dev@bae07fc))
* Use group_by in Polars backend aggregation ([feast-dev#6965](feast-dev#6965)) ([7b9fad2](feast-dev@7b9fad2))
* Use upstream kubectl image as feast-operator CronJob default ([d6cc1dc](feast-dev@d6cc1dc))
* Use UTC end bound and correct docs for disable_event_timestamp ([feast-dev#6956](feast-dev#6956)) ([cc07c82](feast-dev@cc07c82)), closes [feast-dev#6936](feast-dev#6936)

### Features

* Add a non-JVM read path for Lance data sources ([feast-dev#6943](feast-dev#6943)) ([e2a53bb](feast-dev@e2a53bb)), closes [feast-dev#6925](feast-dev#6925) [feast-dev#5782](feast-dev#5782) [feast-dev#6909](feast-dev#6909)
* Add a non-JVM write path for Lance data sources ([feast-dev#6945](feast-dev#6945)) ([f754323](feast-dev@f754323)), closes [feast-dev#6943](feast-dev#6943) [feast-dev#6909](feast-dev#6909)
* Add Chronon online and offline store integrations ([feast-dev#6188](feast-dev#6188)) ([dd059c6](feast-dev@dd059c6))
* Add consistency_level to the Milvus online store config ([97296c1](feast-dev@97296c1))
* Add dualStack server option to the Feast operator ([feast-dev#6887](feast-dev#6887)) ([725a147](feast-dev@725a147)), closes [feast-dev#6977](feast-dev#6977)
* Add Lance optional dependencies ([feast-dev#6958](feast-dev#6958)) ([20bc993](feast-dev@20bc993))
* Add LanceFormat table format with version/tag pinning ([1196e22](feast-dev@1196e22)), closes [feast-dev#5650](feast-dev#5650)
* Add MLflow as a first-class offline DataSource for Feast ([feast-dev#6702](feast-dev#6702)) ([3667772](feast-dev@3667772))
* Add optional GLIDE client for Redis online reads ([feast-dev#6870](feast-dev#6870)) ([6e9a532](feast-dev@6e9a532))
* Add quality monitoring features for Trino offline store ([feast-dev#6779](feast-dev#6779)) ([9340545](feast-dev@9340545))
* Add SavedDatasetLanceStorage ([1118d3e](feast-dev@1118d3e))
* Add standalone MCP server as a first-class component ([0efab5c](feast-dev@0efab5c)), closes [python-keycloak#623](https://github.com/python-keycloak/issues/623)
* Add structured audit logging for MCP feature server ([feast-dev#6456](feast-dev#6456)) ([640ac70](feast-dev@640ac70))
* Add Trino compute engine for batch retrieval and materialization ([feast-dev#6898](feast-dev#6898)) ([11a47b4](feast-dev@11a47b4))
* Batch Postgres online reads across feature views ([feast-dev#6832](feast-dev#6832)) ([514bee7](feast-dev@514bee7)), closes [feast-dev#3259](feast-dev#3259)
* **bigtable:** Make write batch size and concurrency configurable ([feast-dev#6847](feast-dev#6847)) ([5388522](feast-dev@5388522))
* Bucket feature count labels in latency metrics ([feast-dev#6811](feast-dev#6811)) ([d9ea120](feast-dev@d9ea120))
* Expose runtime version in Feast UI ([feast-dev#6843](feast-dev#6843)) ([fa8f06b](feast-dev@fa8f06b))
* Make Milvus index and search params configurable ([ef743ff](feast-dev@ef743ff))
* Offline write batch for IcebergSource ([5be5ed0](feast-dev@5be5ed0))
* OpenLineage consumer improvements - dataset versioning, column lineage, ownership ([69f294e](feast-dev@69f294e))
* **operator:** Add tolerations and nodeSelector to the FeatureStore CR ([feast-dev#6741](feast-dev#6741)) ([03dac6f](feast-dev@03dac6f))
* Serve the MCP server dual-stack on --host :: ([4fc9726](feast-dev@4fc9726))
* Support Milvus partition keys in the Milvus online store ([0ed3285](feast-dev@0ed3285))
* Support token, uri and db_name in the Milvus online store ([c5efecd](feast-dev@c5efecd))
* Version-pinning for FeatureService (online + offline) ([feast-dev#6718](feast-dev#6718)) ([787845a](feast-dev@787845a))

### Performance Improvements

* Avoid pandas copy in Spark reads ([feast-dev#6878](feast-dev#6878)) ([4771156](feast-dev@4771156))
* Decouple metrics HTTP server into a dedicated child process ([feast-dev#6855](feast-dev#6855)) ([0b621de](feast-dev@0b621de))
* Reduce online serving hot-path overhead from metrics and audit logging ([5ee7ee3](feast-dev@5ee7ee3))

---------

Signed-off-by: Srihari <svenkata@redhat.com>
Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
Co-authored-by: Srihari <svenkata@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: feast-ci-bot <feast-ci-bot@willem.co>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants