Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d82dcf2
feat: scaffold Aerospike online store
vkagamlyk Apr 20, 2026
2fa7ba0
feat: implement Aerospike online_write_batch
vkagamlyk Apr 20, 2026
4173e0a
feat: implement Aerospike online_read
vkagamlyk Apr 20, 2026
534b935
feat: implement Aerospike update and teardown
vkagamlyk Apr 20, 2026
fb4dff7
test: add Aerospike unit and integration tests
vkagamlyk Apr 20, 2026
53d5972
feat: add async online_read/write and lifecycle hooks for Aerospike
vkagamlyk Apr 20, 2026
17b1dcb
docs: add Aerospike online store reference and tuning guide
vkagamlyk Apr 20, 2026
f552a94
fix: use bytearray keys and zip-based batch mapping for Aerospike reads
vkagamlyk Apr 20, 2026
ebb3d60
docs: clarify Aerospike auth and TLS sections are Enterprise-only
vkagamlyk Apr 20, 2026
d86dcbf
feat: add aerospike to feast-operator supported online stores
vkagamlyk Apr 20, 2026
5d9e38f
fix(aerospike): project requested_features server-side and surface pe…
vkagamlyk Apr 22, 2026
5553367
feat(aerospike)!: rename total_timeout_ms -> batch_total_timeout_ms a…
vkagamlyk Apr 22, 2026
953b9d1
refactor(aerospike): use MAP_KEY_ORDERED, KEY_DIGEST, and instance-sc…
vkagamlyk Apr 22, 2026
0c8c184
feat(aerospike): add per-FV namespace/set overrides and prewriting hook
vkagamlyk Apr 30, 2026
6628607
test: update aerospike image tag
vkagamlyk Jun 16, 2026
9e76c2f
chore: sync README template and secrets baseline after master merge
vkagamlyk Jun 16, 2026
ea9da18
chore: fix secrets baseline line number for v1 operator types
vkagamlyk Jun 16, 2026
2c37c0f
docs: update aerospike docs
vkagamlyk Jun 16, 2026
e70ba39
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jun 22, 2026
1d016f6
fix(aerospike): wire batch max_retries and fix empty projection handling
vkagamlyk Jun 22, 2026
666cb60
style(aerospike): format online_read docs assignment for ruff
vkagamlyk Jun 22, 2026
7cd0bd3
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jun 25, 2026
dbc45fc
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jun 26, 2026
8dd84e3
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jun 26, 2026
4d5954d
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jun 28, 2026
07738ab
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jun 29, 2026
b4ccaec
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jun 29, 2026
10a1fb3
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jun 29, 2026
b2b98bc
chore: update pixi.lock for aerospike optional extra
vkagamlyk Jun 30, 2026
256d65d
fix(aerospike): add client init lock and batch chunking
vkagamlyk Jun 30, 2026
3766212
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jun 30, 2026
d3ef432
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jul 1, 2026
33f5d37
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jul 1, 2026
d3dc67e
Merge branch 'master' into feat/aerospike-online-store
vkagamlyk Jul 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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>
  • Loading branch information
vkagamlyk and Copilot committed Jun 22, 2026
commit 1d016f6f26405d2d5c84947bf9abd45dcd33b0a8
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,9 @@ def hook(

The hook MUST return a row list with the same shape as its input.
Hooks that raise will fail the whole batch — there is no per-row
fallback. The resolved callable is cached on the store instance, so
swapping the config to a different hook also requires a new
``AerospikeOnlineStore`` instance (which Feast already does on
``RepoConfig`` change).
fallback. The resolved callable is cached on the store instance; if the
configured import string changes between calls, it is re-resolved
automatically on the next write.
"""

user: Optional[str] = None
Expand Down Expand Up @@ -318,6 +317,7 @@ def _get_client(self, config: RepoConfig) -> aerospike.Client:
}
batch_policy: Dict[str, Any] = {
"total_timeout": store_cfg.batch_total_timeout_ms,
"max_retries": store_cfg.max_retries,
}
if store_cfg.socket_timeout_ms is not None:
# socket_timeout is the per-attempt deadline; without it,
Expand Down Expand Up @@ -666,7 +666,7 @@ def online_read(
fv_event_ts_ms = bins.get("event_ts") if bins else None
fv_features = self._normalize_projected_features(raw_features)
docs[user_key] = {
"features": {table.name: fv_features} if fv_features else {},
"features": {table.name: fv_features} if fv_features is not None else {},
"event_timestamps": {table.name: _epoch_ms_to_datetime(fv_event_ts_ms)},
}

Expand Down Expand Up @@ -719,7 +719,7 @@ def _normalize_projected_features(
return raw
if isinstance(raw, list):
if not raw:
return None
return {}
return dict(zip(raw[0::2], raw[1::2]))
Comment thread
vkagamlyk marked this conversation as resolved.
return None

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ def fake_batch_operate(keys, ops):
_fake_batch_record(
key,
{
"features": ["rating", 4.91, "trips_last_7d", 132],
"features": ["rating", 4.91],
"event_ts": _datetime_to_epoch_ms(ts),
},
Comment thread
vkagamlyk marked this conversation as resolved.
)
Expand All @@ -595,8 +595,7 @@ def fake_batch_operate(keys, ops):
ts_out, feats = results[0]
assert ts_out == ts
assert abs(feats["rating"].double_val - 4.91) < 1e-9
assert feats["trips_last_7d"].int64_val == 132

assert feats["trips_last_7d"] == ValueProto()
features_op = captured_ops[0]
assert features_op["op"] == aerospike.OP_MAP_GET_BY_KEY_LIST
assert features_op["bin"] == "features"
Expand All @@ -611,7 +610,7 @@ def test_normalize_projected_features_handles_all_payload_shapes():
"""The shape of the ``features`` payload depends on which op produced it;
the helper must accept all of them."""
assert AerospikeOnlineStore._normalize_projected_features(None) is None
assert AerospikeOnlineStore._normalize_projected_features([]) is None
assert AerospikeOnlineStore._normalize_projected_features([]) == {}
assert AerospikeOnlineStore._normalize_projected_features(["a", 1, "b", 2]) == {
"a": 1,
Comment thread
vkagamlyk marked this conversation as resolved.
"b": 2,
Expand Down