| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
The Aerospike Python client mishandles bytes user keys (hashes only the first byte), collapsing all entities onto the same digest. Wrap keys in bytearray on write and read. Also pair BatchRecord responses with original input keys via zip rather than trusting br.key[2], which the client returns in a different representation on reads. Add two integration tests: cross-FV Map CDT coexistence and update(tables_to_delete=...) background scan. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
…r-record errors Two review blockers rolled into one commit because they share the same code path. 1. Server-side projection. online_read now builds a map_get_by_key_list op nested into the feature-view submap via cdt_ctx_map_key when requested_features is provided, instead of fetching the whole FV slot and filtering in Python. For wide feature views this ships only the requested columns over the wire. The response shape (flat [k,v,k,v] list vs. dict) is normalized through _normalize_projected_features. 2. Per-record error surfacing. Both batch_write and batch_operate only raise when the whole request is rejected; partial failures (single-partition timeout, replica quorum miss) are otherwise silent and present downstream as missing features. online_read now distinguishes RECORD_NOT_FOUND (2) and OP_NOT_APPLICABLE (26, = nested ctx miss when FV slot is absent) from transient errors, which are raised. online_write_batch inspects every per-record result code after the batch call. Unit tests cover all four paths: projected read, not-found, op-not-applicable (nested ctx miss), and a simulated TIMEOUT that must raise. The docker-backed cross-FV and update() integration tests still pass, so server-side projection is verified end-to-end against a real Aerospike server. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
…nd add socket_timeout_ms Review feedback: total_timeout_ms was ambiguous (users read it as a global/end-to-end timeout) and the timeout surface was missing socket_timeout, which is the per-attempt trigger that lets max_retries actually fire within the total budget. * total_timeout_ms -> batch_total_timeout_ms. Now explicitly named after the Aerospike batch policy it maps to, matches read_timeout_ms / write_timeout_ms in framing (each targets one policy scope). * Add socket_timeout_ms (optional). Applies uniformly to read, write and batch policies when set. Leaves the Aerospike client default in place when unset. BREAKING CHANGE: total_timeout_ms is renamed to batch_total_timeout_ms. Config files using the old name must be updated. No default value change. Docs updated (reference + perf-tuning guide) with a short explainer on the per-attempt vs total deadline distinction. Two new unit tests pin the policy wiring: socket_timeout_ms propagates to all three scopes, and is omitted (not injected as None) when unset. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
…oped client
Cheap-win cleanups flagged in review, all touching the same small patch of write-path and lifecycle code.
* Map CDTs are now created with MAP_KEY_ORDERED. map_get_by_key / map_remove_by_key on an ordered map are O(log N) in the map size instead of O(N); matters on reads of wide feature views and on the update() background scan (which walks every record in the project's set).
* Writes drop POLICY_KEY_SEND and rely on the client default (POLICY_KEY_DIGEST). The serialized entity key is no longer stored alongside each record, saving per-record storage the read path never consumes (batch_operate preserves request order; results are paired back by zip in online_read).
* _client moves from a class attribute to an instance attribute (set in __init__). Previously two AerospikeOnlineStore instances could share the cached client through class state until one wrote self._client. With the instance attribute the state is always per-instance from construction.
* Drop MongoDB references from class docstrings and comments (they referred to how the storage layout was derived rather than documenting current behavior). Also rewrite the _build_batch_writes docstring to describe the policies applied on the write path.
Unit test assertions for the write-path record are updated: bw.policy is now None (client default applies) and map ops carry map_policy={'map_order': MAP_KEY_ORDERED}. All three docker-backed integration tests still pass end-to-end (cross-FV upsert, update() background scan, full feature-store round-trip), so the read/write shape survives the ordering and policy changes against a real server.
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Adds three configuration knobs to AerospikeOnlineStoreConfig: - namespace_overrides: pin individual feature views to a different Aerospike namespace (e.g. RAM-only vs. SSD-backed) without splitting the project across stores. - set_overrides: place a feature view in its own set so admin ops on it (truncate, scan-based deletes during `feast apply`) do not touch records of other views. - prewriting_hook: import-string-resolved callable invoked once per online_write_batch with the rows about to be written, returning the rows that actually go on the wire. Resolved and cached on first use; returning [] short-circuits the wire call. Read, write, update and teardown paths all honour the per-FV ns/set resolution. update() groups dropped feature views by their resolved (ns, set) pair and issues one background scan per group. teardown() truncates every unique (ns, set) pair the project may have written to, including the store-level default. Adds 22 unit tests for the new behaviour and updates 3 existing call sites of _build_batch_writes for the new namespace= parameter. Adds a sample hook module under examples/online_store/aerospike_overrides_and_hooks/ and corresponding sections in docs/reference/online-stores/aerospike.md. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Adding aerospike to the feast-operator enum shifted the allowlisted SecretRef entry in api/v1/featurestore_types.go by one line. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
|
@cocdex review |
Sorry, something went wrong.
There was a problem hiding this comment.
Adds a first-party Aerospike online store backend to Feast’s Python SDK, along with universal-suite wiring, operator/CRD updates, and end-user documentation/examples.
Changes:
Copilot reviewed 21 out of 22 changed files in this pull request and generated 7 comments.
Show a summary per file| File | Description |
|---|---|
| sdk/python/tests/universal/feature_repos/universal/online_store/aerospike.py | Universal-suite containerized Aerospike CE creator used by integration runs |
| sdk/python/tests/unit/online_store/test_aerospike_online_retrieval.py | Unit + Docker integration tests covering Aerospike store behaviors |
| sdk/python/feast/repo_config.py | Registers type: aerospike → Aerospike online store class mapping |
| sdk/python/feast/infra/online_stores/aerospike_online_store/aerospike.py | Core Aerospike online store implementation + config model |
| sdk/python/feast/infra/online_stores/aerospike_online_store/aerospike_repo_configuration.py | Opt-in universal-suite repo configuration module for Aerospike |
| sdk/python/feast/infra/online_stores/aerospike_online_store/init.py | Package exports for Aerospike online store/config |
| README.md | Adds Aerospike to the high-level online store list |
| pyproject.toml | Adds feast[aerospike] optional dependency extra |
| infra/feast-operator/dist/install.yaml | Adds aerospike to operator-installed CRD enums |
| infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml | Adds aerospike to CRD enum validation |
| infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml | Adds aerospike to bundled manifest CRD enum validation |
| infra/feast-operator/api/v1alpha1/featurestore_types.go | Adds aerospike to operator API enum + valid type list |
| infra/feast-operator/api/v1/featurestore_types.go | Adds aerospike to operator API enum + valid type list |
| examples/online_store/aerospike_overrides_and_hooks/README.md | Example documentation for overrides + prewriting hooks |
| examples/online_store/aerospike_overrides_and_hooks/hooks.py | Sample prewriting hook implementations (PII hashing, row filtering) |
| examples/online_store/aerospike_overrides_and_hooks/feature_store.yaml | Example config snippet showing overrides + hook wiring |
| docs/SUMMARY.md | Adds Aerospike reference page to docs navigation |
| docs/roadmap.md | Marks Aerospike online store as implemented |
| docs/reference/online-stores/README.md | Links Aerospike reference page |
| docs/reference/online-stores/aerospike.md | New Aerospike online store reference documentation |
| docs/how-to-guides/online-server-performance-tuning.md | Adds Aerospike to tuning guidance + comparison tables |
| .secrets.baseline | Updates detect-secrets baseline metadata/line numbers |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
Copilot review feedback on PR feast-dev#6532: - Add max_retries to the batch client policy (batch_operate/batch_write path) - Treat empty projected feature maps as present FV slots (is not None) - Return {} from _normalize_projected_features([]) instead of None - Fix projection unit test mock/assertions - Correct prewriting_hook config docstring Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot review feedback on PR feast-dev#6532: - Add max_retries to the batch client policy (batch_operate/batch_write path) - Treat empty projected feature maps as present FV slots (is not None) - Return {} from _normalize_projected_features([]) instead of None - Fix projection unit test mock/assertions - Correct prewriting_hook config docstring Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
|
Hi @franciscojavierarceo, are you able to take a look at this PR? We are really excited to have a feast integration, customers have been making custom ones and we want to get something official! About us: |
Sorry, something went wrong.
|
@vkagamlyk Need to generate pixi.lock file to update dependencies |
Sorry, something went wrong.
Regenerate the v6 lockfile with Pixi v0.63.1 after adding the aerospike extra to pyproject.toml. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
|
@vkagamlyk looks good overall,
_get_client has no locking. In a threaded feature server (the default deployment), two concurrent requests can both create a client, one gets silently leaked (never closed). Other online stores like Redis and MongoDB both handle this correctly.
Aerospike's server-side batch-max-requests defaults to 5,000 records ? If online_write_batch receives more than that (common during feast materialize), the entire batch fails with a server error. (DynamoDB's store chunks at 25, Redis pipelines in segments.) |
Sorry, something went wrong.
Guard lazy client creation with a lock to avoid connection leaks under concurrent first use, and chunk batch reads/writes by batch_max_records so large materializations stay under Aerospike server batch limits. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Thank you for review @ntkathole. Addressed in 256d65d |
Sorry, something went wrong.
There was a problem hiding this comment.
Looks good, Thank you @vkagamlyk for contribution!
Sorry, something went wrong.
* feat: scaffold Aerospike online store
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* feat: implement Aerospike online_write_batch
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* feat: implement Aerospike online_read
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* feat: implement Aerospike update and teardown
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* test: add Aerospike unit and integration tests
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* feat: add async online_read/write and lifecycle hooks for Aerospike
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* docs: add Aerospike online store reference and tuning guide
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* fix: use bytearray keys and zip-based batch mapping for Aerospike reads
The Aerospike Python client mishandles bytes user keys (hashes only the first byte), collapsing all entities onto the same digest. Wrap keys in bytearray on write and read. Also pair BatchRecord responses with original input keys via zip rather than trusting br.key[2], which the client returns in a different representation on reads.
Add two integration tests: cross-FV Map CDT coexistence and update(tables_to_delete=...) background scan.
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* docs: clarify Aerospike auth and TLS sections are Enterprise-only
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* feat: add aerospike to feast-operator supported online stores
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* fix(aerospike): project requested_features server-side and surface per-record errors
Two review blockers rolled into one commit because they share the same code path.
1. Server-side projection. online_read now builds a map_get_by_key_list op nested into the feature-view submap via cdt_ctx_map_key when requested_features is provided, instead of fetching the whole FV slot and filtering in Python. For wide feature views this ships only the requested columns over the wire. The response shape (flat [k,v,k,v] list vs. dict) is normalized through _normalize_projected_features.
2. Per-record error surfacing. Both batch_write and batch_operate only raise when the whole request is rejected; partial failures (single-partition timeout, replica quorum miss) are otherwise silent and present downstream as missing features. online_read now distinguishes RECORD_NOT_FOUND (2) and OP_NOT_APPLICABLE (26, = nested ctx miss when FV slot is absent) from transient errors, which are raised. online_write_batch inspects every per-record result code after the batch call.
Unit tests cover all four paths: projected read, not-found, op-not-applicable (nested ctx miss), and a simulated TIMEOUT that must raise. The docker-backed cross-FV and update() integration tests still pass, so server-side projection is verified end-to-end against a real Aerospike server.
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* feat(aerospike)!: rename total_timeout_ms -> batch_total_timeout_ms and add socket_timeout_ms
Review feedback: total_timeout_ms was ambiguous (users read it as a global/end-to-end timeout) and the timeout surface was missing socket_timeout, which is the per-attempt trigger that lets max_retries actually fire within the total budget.
* total_timeout_ms -> batch_total_timeout_ms. Now explicitly named after the Aerospike batch policy it maps to, matches read_timeout_ms / write_timeout_ms in framing (each targets one policy scope).
* Add socket_timeout_ms (optional). Applies uniformly to read, write and batch policies when set. Leaves the Aerospike client default in place when unset.
BREAKING CHANGE: total_timeout_ms is renamed to batch_total_timeout_ms. Config files using the old name must be updated. No default value change.
Docs updated (reference + perf-tuning guide) with a short explainer on the per-attempt vs total deadline distinction. Two new unit tests pin the policy wiring: socket_timeout_ms propagates to all three scopes, and is omitted (not injected as None) when unset.
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* refactor(aerospike): use MAP_KEY_ORDERED, KEY_DIGEST, and instance-scoped client
Cheap-win cleanups flagged in review, all touching the same small patch of write-path and lifecycle code.
* Map CDTs are now created with MAP_KEY_ORDERED. map_get_by_key / map_remove_by_key on an ordered map are O(log N) in the map size instead of O(N); matters on reads of wide feature views and on the update() background scan (which walks every record in the project's set).
* Writes drop POLICY_KEY_SEND and rely on the client default (POLICY_KEY_DIGEST). The serialized entity key is no longer stored alongside each record, saving per-record storage the read path never consumes (batch_operate preserves request order; results are paired back by zip in online_read).
* _client moves from a class attribute to an instance attribute (set in __init__). Previously two AerospikeOnlineStore instances could share the cached client through class state until one wrote self._client. With the instance attribute the state is always per-instance from construction.
* Drop MongoDB references from class docstrings and comments (they referred to how the storage layout was derived rather than documenting current behavior). Also rewrite the _build_batch_writes docstring to describe the policies applied on the write path.
Unit test assertions for the write-path record are updated: bw.policy is now None (client default applies) and map ops carry map_policy={'map_order': MAP_KEY_ORDERED}. All three docker-backed integration tests still pass end-to-end (cross-FV upsert, update() background scan, full feature-store round-trip), so the read/write shape survives the ordering and policy changes against a real server.
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* feat(aerospike): add per-FV namespace/set overrides and prewriting hook
Adds three configuration knobs to AerospikeOnlineStoreConfig:
- namespace_overrides: pin individual feature views to a different
Aerospike namespace (e.g. RAM-only vs. SSD-backed) without splitting
the project across stores.
- set_overrides: place a feature view in its own set so admin ops on
it (truncate, scan-based deletes during `feast apply`) do not touch
records of other views.
- prewriting_hook: import-string-resolved callable invoked once per
online_write_batch with the rows about to be written, returning the
rows that actually go on the wire. Resolved and cached on first use;
returning [] short-circuits the wire call.
Read, write, update and teardown paths all honour the per-FV ns/set
resolution. update() groups dropped feature views by their resolved
(ns, set) pair and issues one background scan per group. teardown()
truncates every unique (ns, set) pair the project may have written to,
including the store-level default.
Adds 22 unit tests for the new behaviour and updates 3 existing call
sites of _build_batch_writes for the new namespace= parameter. Adds a
sample hook module under examples/online_store/aerospike_overrides_and_hooks/
and corresponding sections in docs/reference/online-stores/aerospike.md.
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* test: update aerospike image tag
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* chore: sync README template and secrets baseline after master merge
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* chore: fix secrets baseline line number for v1 operator types
Adding aerospike to the feast-operator enum shifted the allowlisted
SecretRef entry in api/v1/featurestore_types.go by one line.
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* docs: update aerospike docs
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* fix(aerospike): wire batch max_retries and fix empty projection handling
Copilot review feedback on PR feast-dev#6532:
- Add max_retries to the batch client policy (batch_operate/batch_write path)
- Treat empty projected feature maps as present FV slots (is not None)
- Return {} from _normalize_projected_features([]) instead of None
- Fix projection unit test mock/assertions
- Correct prewriting_hook config docstring
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* style(aerospike): format online_read docs assignment for ruff
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* chore: update pixi.lock for aerospike optional extra
Regenerate the v6 lockfile with Pixi v0.63.1 after adding the aerospike extra to pyproject.toml.
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
* fix(aerospike): add client init lock and batch chunking
Guard lazy client creation with a lock to avoid connection leaks under concurrent first use, and chunk batch reads/writes by batch_max_records so large materializations stay under Aerospike server batch limits.
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
---------
Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
# [0.65.0](v0.64.0...v0.65.0) (2026-07-20) ### Bug Fixes * add debug logging for FIPS mode detection fallback ([6c1b24e](6c1b24e)) * Build embedded UI from local source ([#6525](#6525)) ([3500349](3500349)) * Bump decommissioned Snowflake Python UDF runtime from 3.9 to 3.10 ([#6606](#6606)) ([#6608](#6608)) ([10341e4](10341e4)) * configure FIPS-compliant gRPC cipher suites for offline server ([6bc80a2](6bc80a2)) * Correct Flink PyArrow dependency constraints ([#6604](#6604)) ([70a9751](70a9751)) * Fix ValueError in signal handling for Trino worker threads ([#6428](#6428)) ([506d919](506d919)) * Fixed monitoring page issues ([7946018](7946018)) * Make pytest config compatible with newer pytest ([#5779](#5779)) ([a57ea33](a57ea33)) * Replace comma with space in DynamoDB-incompatible label tag value ([51e3a16](51e3a16)) * Resolve UI build warnings ([#6529](#6529)) ([abe92af](abe92af)) * Unblock nightly UI build ([#6570](#6570)) ([f296d4b](f296d4b)) * Use LONGBLOB for SQL registry proto columns on MySQL ([#6566](#6566)) ([7e4beb2](7e4beb2)) ### Features * Add click-to-zoom lightbox for blog post images ([#6575](#6575)) ([1cb23fd](1cb23fd)) * Add dark mode support to website and blog ([#6589](#6589)) ([7358fb8](7358fb8)) * Add OnlineStore for Aerospike ([#6532](#6532)) ([9cd35e1](9cd35e1)) * Add OpenLineage Consumer to Feast - receive, store, and visualize cross-producer lineage ([#6549](#6549)) ([a834126](a834126)) * Add registry list feature views by updated since ([#6092](#6092)) ([#6093](#6093)) ([006c606](006c606)) * Add ScyllaDB online store with vector search ([#6508](#6508)) ([1669661](1669661)) * Added compute and jobs UI ([ba2c05c](ba2c05c)) * Added Iceberg REST Catalog data source support ([e0a8573](e0a8573)) * Bring Your Own Spark - SparkApplication ([#6550](#6550)) ([dcd496f](dcd496f)) * **cassandra:** Add multi-DC support via per-datacenter execution profiles ([#6434](#6434)) ([0de9196](0de9196)) * Enhanced data source creation as a visual catalog with type-specific forms ([#6557](#6557)) ([d6acbba](d6acbba)) * Enhanced datasets UI functionality ([de11152](de11152)) * Implement RegistryServer.Proto RPC with RBAC-filtered response ([#6558](#6558)) ([#6552](#6552)) ([0d02614](0d02614)) * New zoned timestamp feature type ([#6536](#6536)) ([#6537](#6537)) ([eb042f0](eb042f0)) * **operator:** Auto-create RBAC for spark_application batch engine ([#6597](#6597)) ([f487b37](f487b37)) * **operator:** integrate cluster TLS profile for OCP 5.0 compliance ([43263a6](43263a6)) * Permissions CRUD UI and OIDC auth integration in UI ([6511da1](6511da1)) * Retrieve historical features from BigQuery without entity_df ([#6569](#6569)) ([cd5f6bb](cd5f6bb)), closes [#6558](#6558) [#6552](#6552) * **spark:** SparkSource query+path and pre-computed offline read for BatchFeatureView ([#6440](#6440)) ([4dc8757](4dc8757)) ### BREAKING CHANGES * total_timeout_ms is renamed to batch_total_timeout_ms. Config files using the old name must be updated. No default value change. Docs updated (reference + perf-tuning guide) with a short explainer on the per-attempt vs total deadline distinction. Two new unit tests pin the policy wiring: socket_timeout_ms propagates to all three scopes, and is omitted (not injected as None) when unset. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * refactor(aerospike): use MAP_KEY_ORDERED, KEY_DIGEST, and instance-scoped client Cheap-win cleanups flagged in review, all touching the same small patch of write-path and lifecycle code. * Map CDTs are now created with MAP_KEY_ORDERED. map_get_by_key / map_remove_by_key on an ordered map are O(log N) in the map size instead of O(N); matters on reads of wide feature views and on the update() background scan (which walks every record in the project's set). * Writes drop POLICY_KEY_SEND and rely on the client default (POLICY_KEY_DIGEST). The serialized entity key is no longer stored alongside each record, saving per-record storage the read path never consumes (batch_operate preserves request order; results are paired back by zip in online_read). * _client moves from a class attribute to an instance attribute (set in __init__). Previously two AerospikeOnlineStore instances could share the cached client through class state until one wrote self._client. With the instance attribute the state is always per-instance from construction. * Drop MongoDB references from class docstrings and comments (they referred to how the storage layout was derived rather than documenting current behavior). Also rewrite the _build_batch_writes docstring to describe the policies applied on the write path. Unit test assertions for the write-path record are updated: bw.policy is now None (client default applies) and map ops carry map_policy={'map_order': MAP_KEY_ORDERED}. All three docker-backed integration tests still pass end-to-end (cross-FV upsert, update() background scan, full feature-store round-trip), so the read/write shape survives the ordering and policy changes against a real server. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * feat(aerospike): add per-FV namespace/set overrides and prewriting hook Adds three configuration knobs to AerospikeOnlineStoreConfig: - namespace_overrides: pin individual feature views to a different Aerospike namespace (e.g. RAM-only vs. SSD-backed) without splitting the project across stores. - set_overrides: place a feature view in its own set so admin ops on it (truncate, scan-based deletes during `feast apply`) do not touch records of other views. - prewriting_hook: import-string-resolved callable invoked once per online_write_batch with the rows about to be written, returning the rows that actually go on the wire. Resolved and cached on first use; returning [] short-circuits the wire call. Read, write, update and teardown paths all honour the per-FV ns/set resolution. update() groups dropped feature views by their resolved (ns, set) pair and issues one background scan per group. teardown() truncates every unique (ns, set) pair the project may have written to, including the store-level default. Adds 22 unit tests for the new behaviour and updates 3 existing call sites of _build_batch_writes for the new namespace= parameter. Adds a sample hook module under examples/online_store/aerospike_overrides_and_hooks/ and corresponding sections in docs/reference/online-stores/aerospike.md. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * test: update aerospike image tag Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: sync README template and secrets baseline after master merge Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: fix secrets baseline line number for v1 operator types Adding aerospike to the feast-operator enum shifted the allowlisted SecretRef entry in api/v1/featurestore_types.go by one line. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * docs: update aerospike docs Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * fix(aerospike): wire batch max_retries and fix empty projection handling Copilot review feedback on PR #6532: - Add max_retries to the batch client policy (batch_operate/batch_write path) - Treat empty projected feature maps as present FV slots (is not None) - Return {} from _normalize_projected_features([]) instead of None - Fix projection unit test mock/assertions - Correct prewriting_hook config docstring Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * style(aerospike): format online_read docs assignment for ruff Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: update pixi.lock for aerospike optional extra Regenerate the v6 lockfile with Pixi v0.63.1 after adding the aerospike extra to pyproject.toml. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * fix(aerospike): add client init lock and batch chunking Guard lazy client creation with a lock to avoid connection leaks under concurrent first use, and chunk batch reads/writes by batch_max_records so large materializations stay under Aerospike server batch limits. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
# [0.65.0](feast-dev/feast@v0.64.0...v0.65.0) (2026-07-20) ### Bug Fixes * add debug logging for FIPS mode detection fallback ([6c1b24e](feast-dev@6c1b24e)) * Build embedded UI from local source ([feast-dev#6525](feast-dev#6525)) ([3500349](feast-dev@3500349)) * Bump decommissioned Snowflake Python UDF runtime from 3.9 to 3.10 ([feast-dev#6606](feast-dev#6606)) ([feast-dev#6608](feast-dev#6608)) ([10341e4](feast-dev@10341e4)) * configure FIPS-compliant gRPC cipher suites for offline server ([6bc80a2](feast-dev@6bc80a2)) * Correct Flink PyArrow dependency constraints ([feast-dev#6604](feast-dev#6604)) ([70a9751](feast-dev@70a9751)) * Fix ValueError in signal handling for Trino worker threads ([feast-dev#6428](feast-dev#6428)) ([506d919](feast-dev@506d919)) * Fixed monitoring page issues ([7946018](feast-dev@7946018)) * Make pytest config compatible with newer pytest ([feast-dev#5779](feast-dev#5779)) ([a57ea33](feast-dev@a57ea33)) * Replace comma with space in DynamoDB-incompatible label tag value ([51e3a16](feast-dev@51e3a16)) * Resolve UI build warnings ([feast-dev#6529](feast-dev#6529)) ([abe92af](feast-dev@abe92af)) * Unblock nightly UI build ([feast-dev#6570](feast-dev#6570)) ([f296d4b](feast-dev@f296d4b)) * Use LONGBLOB for SQL registry proto columns on MySQL ([feast-dev#6566](feast-dev#6566)) ([7e4beb2](feast-dev@7e4beb2)) ### Features * Add click-to-zoom lightbox for blog post images ([feast-dev#6575](feast-dev#6575)) ([1cb23fd](feast-dev@1cb23fd)) * Add dark mode support to website and blog ([feast-dev#6589](feast-dev#6589)) ([7358fb8](feast-dev@7358fb8)) * Add OnlineStore for Aerospike ([feast-dev#6532](feast-dev#6532)) ([9cd35e1](feast-dev@9cd35e1)) * Add OpenLineage Consumer to Feast - receive, store, and visualize cross-producer lineage ([feast-dev#6549](feast-dev#6549)) ([a834126](feast-dev@a834126)) * Add registry list feature views by updated since ([feast-dev#6092](feast-dev#6092)) ([feast-dev#6093](feast-dev#6093)) ([006c606](feast-dev@006c606)) * Add ScyllaDB online store with vector search ([feast-dev#6508](feast-dev#6508)) ([1669661](feast-dev@1669661)) * Added compute and jobs UI ([ba2c05c](feast-dev@ba2c05c)) * Added Iceberg REST Catalog data source support ([e0a8573](feast-dev@e0a8573)) * Bring Your Own Spark - SparkApplication ([feast-dev#6550](feast-dev#6550)) ([dcd496f](feast-dev@dcd496f)) * **cassandra:** Add multi-DC support via per-datacenter execution profiles ([feast-dev#6434](feast-dev#6434)) ([0de9196](feast-dev@0de9196)) * Enhanced data source creation as a visual catalog with type-specific forms ([feast-dev#6557](feast-dev#6557)) ([d6acbba](feast-dev@d6acbba)) * Enhanced datasets UI functionality ([de11152](feast-dev@de11152)) * Implement RegistryServer.Proto RPC with RBAC-filtered response ([feast-dev#6558](feast-dev#6558)) ([feast-dev#6552](feast-dev#6552)) ([0d02614](feast-dev@0d02614)) * New zoned timestamp feature type ([feast-dev#6536](feast-dev#6536)) ([feast-dev#6537](feast-dev#6537)) ([eb042f0](feast-dev@eb042f0)) * **operator:** Auto-create RBAC for spark_application batch engine ([feast-dev#6597](feast-dev#6597)) ([f487b37](feast-dev@f487b37)) * **operator:** integrate cluster TLS profile for OCP 5.0 compliance ([43263a6](feast-dev@43263a6)) * Permissions CRUD UI and OIDC auth integration in UI ([6511da1](feast-dev@6511da1)) * Retrieve historical features from BigQuery without entity_df ([feast-dev#6569](feast-dev#6569)) ([cd5f6bb](feast-dev@cd5f6bb)), closes [feast-dev#6558](feast-dev#6558) [feast-dev#6552](feast-dev#6552) * **spark:** SparkSource query+path and pre-computed offline read for BatchFeatureView ([feast-dev#6440](feast-dev#6440)) ([4dc8757](feast-dev@4dc8757)) ### BREAKING CHANGES * total_timeout_ms is renamed to batch_total_timeout_ms. Config files using the old name must be updated. No default value change. Docs updated (reference + perf-tuning guide) with a short explainer on the per-attempt vs total deadline distinction. Two new unit tests pin the policy wiring: socket_timeout_ms propagates to all three scopes, and is omitted (not injected as None) when unset. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * refactor(aerospike): use MAP_KEY_ORDERED, KEY_DIGEST, and instance-scoped client Cheap-win cleanups flagged in review, all touching the same small patch of write-path and lifecycle code. * Map CDTs are now created with MAP_KEY_ORDERED. map_get_by_key / map_remove_by_key on an ordered map are O(log N) in the map size instead of O(N); matters on reads of wide feature views and on the update() background scan (which walks every record in the project's set). * Writes drop POLICY_KEY_SEND and rely on the client default (POLICY_KEY_DIGEST). The serialized entity key is no longer stored alongside each record, saving per-record storage the read path never consumes (batch_operate preserves request order; results are paired back by zip in online_read). * _client moves from a class attribute to an instance attribute (set in __init__). Previously two AerospikeOnlineStore instances could share the cached client through class state until one wrote self._client. With the instance attribute the state is always per-instance from construction. * Drop MongoDB references from class docstrings and comments (they referred to how the storage layout was derived rather than documenting current behavior). Also rewrite the _build_batch_writes docstring to describe the policies applied on the write path. Unit test assertions for the write-path record are updated: bw.policy is now None (client default applies) and map ops carry map_policy={'map_order': MAP_KEY_ORDERED}. All three docker-backed integration tests still pass end-to-end (cross-FV upsert, update() background scan, full feature-store round-trip), so the read/write shape survives the ordering and policy changes against a real server. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * feat(aerospike): add per-FV namespace/set overrides and prewriting hook Adds three configuration knobs to AerospikeOnlineStoreConfig: - namespace_overrides: pin individual feature views to a different Aerospike namespace (e.g. RAM-only vs. SSD-backed) without splitting the project across stores. - set_overrides: place a feature view in its own set so admin ops on it (truncate, scan-based deletes during `feast apply`) do not touch records of other views. - prewriting_hook: import-string-resolved callable invoked once per online_write_batch with the rows about to be written, returning the rows that actually go on the wire. Resolved and cached on first use; returning [] short-circuits the wire call. Read, write, update and teardown paths all honour the per-FV ns/set resolution. update() groups dropped feature views by their resolved (ns, set) pair and issues one background scan per group. teardown() truncates every unique (ns, set) pair the project may have written to, including the store-level default. Adds 22 unit tests for the new behaviour and updates 3 existing call sites of _build_batch_writes for the new namespace= parameter. Adds a sample hook module under examples/online_store/aerospike_overrides_and_hooks/ and corresponding sections in docs/reference/online-stores/aerospike.md. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * test: update aerospike image tag Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: sync README template and secrets baseline after master merge Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: fix secrets baseline line number for v1 operator types Adding aerospike to the feast-operator enum shifted the allowlisted SecretRef entry in api/v1/featurestore_types.go by one line. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * docs: update aerospike docs Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * fix(aerospike): wire batch max_retries and fix empty projection handling Copilot review feedback on PR feast-dev#6532: - Add max_retries to the batch client policy (batch_operate/batch_write path) - Treat empty projected feature maps as present FV slots (is not None) - Return {} from _normalize_projected_features([]) instead of None - Fix projection unit test mock/assertions - Correct prewriting_hook config docstring Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * style(aerospike): format online_read docs assignment for ruff Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: update pixi.lock for aerospike optional extra Regenerate the v6 lockfile with Pixi v0.63.1 after adding the aerospike extra to pyproject.toml. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * fix(aerospike): add client init lock and batch chunking Guard lazy client creation with a lock to avoid connection leaks under concurrent first use, and chunk batch reads/writes by batch_max_records so large materializations stay under Aerospike server batch limits. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
| Back | FazBrowse Home | New Git URL |
What this PR does / why we need it
Adds a first-class Aerospike online store integration at
feast.infra.online_stores.aerospike_online_store, backed by the official
aerospike>=19 Python client and targeting Aerospike server 6.0+
(developed and tested against CE 8.x).
Aerospike is a low-latency distributed key-value store widely deployed for
real-time ML feature serving. This integration gives Feast users a managed path
to Aerospike for online retrieval.
Storage layout
Each entity is stored as a single Aerospike record keyed by the serialized
entity key. Multiple feature views for the same entity share one record using
Map CDT bins:
namespace: <config.namespace> # default: "feast" set: <set_name_template> # default: "{project}_{collection_suffix}" → e.g. my_repo_latest key: bytearray(serialize_entity_key(entity_key)) bins: features : map<fv_name, map<feature_name, native_value>> event_ts : map<fv_name, epoch_ms> created_ts : epoch_ms # optional, single top-level value record TTL: config.ttl_seconds # record-level (-1 = never, 0 → never, unset → namespace default)Default: one set per project ({project}_latest). Per-feature-view isolation
is opt-in via set_overrides (see below).
Writes use Aerospike batch_write with Map CDT map_put_items /
map_put ops so concurrent writers touching different feature views on the same
entity never clobber each other. Reads use batch_operate with server-side
Map-get projection when requested_features is provided.
Implementation highlights
online_write_batch_async, online_read_async, initialize(), and
close(). Async methods wrap the blocking client via run_in_executor.
Native asyncio client adoption is tracked as a follow-up.
map_get_by_key_list nested into the feature-view submap via cdt_ctx_map_key
so only requested columns are returned from the server.
when the whole request is rejected; this store inspects per-record result
codes and raises on transient failures (RECORD_NOT_FOUND and
OP_NOT_APPLICABLE are treated as missing features).
bytearray, not bytes. The client hashes only the first byte of bytes
keys during digest computation, causing silent collisions; bytearray uses
the intended binary-key digest.
are paired back via zip rather than re-parsing br.key[2].
O(log N) lookups on wide feature views and on the update() background scan.
serialized entity key is not stored redundantly on the server.
schema changes for multi-entity keys.
expire, >0 → explicit seconds.
set_overrides pin individual feature views to different namespaces or sets
without splitting the project across stores. update() and teardown()
honour resolved (namespace, set) pairs.
online_write_batch for PII masking, encryption, coercion, etc.
batch_total_timeout_ms (per-batch total deadline including retries), and
optional socket_timeout_ms (per-attempt, propagates to all three policies).
(tls / tls_ca_file) are plumbed through the config but are config-only
in v1 on Aerospike CE (not exercised in GitHub Actions). Documented in the
reference page.
Tests
~57 pure-Python unit tests (no Docker required) covering:
MAP_KEY_ORDERED policy, empty-batch short-circuit
3 Docker-backed integration tests via testcontainers (Aerospike CE 8 —
aerospike/aerospike-server:8.0.0.10_1):
missing-key → None across int, string, and composite entity keys
entity coexist (Map CDT upsert semantics)
scan removes a dropped FV slot while the surviving FV stays intact
Universal online-store suite wiring — ships AerospikeOnlineStoreCreator
plus a FULL_REPO_CONFIGS module for opt-in via
FULL_REPO_CONFIGS_MODULE=feast.infra.online_stores.aerospike_online_store.aerospike_repo_configuration.
Default-matrix registration is deferred to a follow-up PR (MongoDB, Couchbase,
Cassandra, MySQL pattern).
Documentation
model, CE vs EE matrix, overrides, prewriting hook, tuning).
tuning subsection.
override config.
feast-operator
Adds aerospike to supported online store types in feast-operator CRDs and
bundled manifests.
Out of scope for v1 (follow-ups)
routes to online_read_async / online_write_batch_async (methods exist;
property still inherits the base read=False, write=False default).
Known follow-ups before upstream PR
(reviewer note: same pattern as MongoDB preview banner).
upstream benchmarks PR lands.
Checks
Testing strategy
Misc
Aerospike client dependency is gated behind the aerospike optional extra
(pip install 'feast[aerospike]'), so existing installs that don't need it pay
no import cost.