feat: Add feature view versioning to Hazelcast online store - #6757
Open
arose26 wants to merge 1 commit into
Open
feat: Add feature view versioning to Hazelcast online store#6757arose26 wants to merge 1 commit into
arose26 wants to merge 1 commit into
Conversation
Thread registry.enable_online_feature_view_versioning through _map_name, which
now delegates to compute_table_id, so that with versioning enabled each feature
view version gets its own Hazelcast map (test_project_driver_stats_v2) instead
of all versions sharing one.
Hazelcast already namespaced as {project}_{table.name}, so this is the same
compute_table_id convention the Milvus and FAISS stores use and the map name is
unchanged when versioning is disabled.
The update() and teardown() SQL statements bind the resolved name to a local
first rather than calling _map_name inside the f-string: line breaks inside an
f-string replacement field are a Python 3.12 feature and this package supports
3.10.
HazelcastOnlineStore is added to the versioned-read allowlist. Its online_read
iterates the requested entity keys and appends (None, None) for a miss, so it
returns one aligned entry per key as the OnlineStore contract requires; a test
pins that property directly.
Also adds Milvus to the VersionedOnlineReadNotSupported message, which has
listed it as unsupported since it was allowlisted.
Part of feast-dev#2728. Closes feast-dev#6174
Signed-off-by: arose26 <145766958+arose26@users.noreply.github.com>
arose26
requested review from
nquinn408,
shuchu and
tokoko
and removed request for
a team
August 18, 2026 13:27
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #6174. Part of #2728.
What this does
Threads
registry.enable_online_feature_view_versioningthrough_map_name, which nowdelegates to
compute_table_id, so that with versioning enabled each feature view versiongets its own Hazelcast map (
test_project_driver_stats_v2) instead of all versions sharingone. Applied to every call site —
online_write_batch,online_read,update(both thekeep and delete loops) and
teardown.Hazelcast already namespaced as
{project}_{table.name}, so this is the samecompute_table_idconvention the merged Milvus (#6330) and FAISS (#6256) stores use — nodeviation. With versioning disabled the map name is byte-identical to today's, pinned by the
versioning=Falsecases.One small refactor, and why it is necessary
update()andteardown()previously called_map_name(...)inline inside f-strings:With the extra argument that call no longer fits on one line, and line breaks inside an
f-string replacement field are a Python 3.12 feature (PEP 701) while this package declares
python_requires=">=3.10". So the resolved name is bound to a local first and the f-stringsjust interpolate it.
ruffwith the project'spy310target rejects the inline form, whichis how I caught it.
Versioned-read allowlist: added, after checking
HazelcastOnlineStoreis added toOnlineStore._is_versioned_read_supported(). I read thepath rather than assuming:
online_readbuildsentity_keys_strfrom the requested keys inorder, then iterates it appending
(event_ts, entry)for a hit and(None, None)for a miss —so it returns one aligned entry per requested key, which is the contract
sqlite.pyimplementsand the property versioned reads depend on.
test_read_returns_one_entry_per_requested_keypins it directly rather than taking my word for it.
Write and read also both serialize entity keys at version 3, so they agree on keys and the
change does not desynchronise them.
Drive-by: a stale error message
VersionedOnlineReadNotSupportedlisted "SQLite, PostgreSQL, MySQL, FAISS, Redis, andDynamoDB", but
_is_versioned_read_supported()has includedMilvusOnlineStoresince #6330,which updated
online_store.pywithout touchingerrors.py. So the message has been tellingMilvus users their store is unsupported while the code supported it. Added Milvus alongside
Hazelcast — happy to split that into its own PR if you'd prefer.
Tests
New
sdk/python/tests/unit/infra/online_store/test_hazelcast_versioning.py, 15 tests,MagicMock-based in the same style as the mergedtest_milvus_versioning.py, andimportorskip-guarded onhazelcast._v2when on;projection.version_tagtakes priority overcurrent_version_number; version0gets nosuffix; two versions never collide
update(create and drop) andteardownall operate on theversioned map — write is parametrized so the unversioned case is asserted as the control
_is_versioned_read_supported()is true,_check_versioned_read_supportnolonger raises, and the alignment property the allowlist rests on is asserted
Verified red-before/green-after: with the three source files reverted, seven of these fail,
while the
versioning=Falsecontrol and the read-alignment test still pass — the lattercorrectly, since alignment is a pre-existing property this PR relies on rather than introduces.
Regression check across the 55 unit test files touching online stores or versioning: the set of
failing and erroring tests is identical with and without this change (
diffof the sortedFAILED/ERRORlines is empty). Those pre-existing failures are missing optional dependenciesin my environment.
ruff check,ruff formatandmypyare clean on all four files.🤖 Written with Claude Code (Claude Opus 5), reviewed by @arose26.