Skip to content

validator: Alternator API test#392

Closed
m-szymon wants to merge 6 commits into
scylladb:masterfrom
m-szymon:alternator_tests
Closed

validator: Alternator API test#392
m-szymon wants to merge 6 commits into
scylladb:masterfrom
m-szymon:alternator_tests

Conversation

@m-szymon

@m-szymon m-szymon commented Mar 17, 2026

Copy link
Copy Markdown
Collaborator

Add Alternator validator coverage for the main request paths exercised by
the Vector Store integration.

The new tests cover table creation, table updates, and table deletion, as
well as item operations including put, update, delete, and batch writes.
They also verify query behavior, including vector search requests and
result limiting.

Necessary AWS SDK dependencies are added to enable Alternator client.

Fixes: https://scylladb.atlassian.net/browse/VECTOR-581

@nyh

nyh commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

Nice!
Does the Rust AWS SDK just let you add the parameters we invented, like VectorIndexes etc., without checking? That's nice - I was worried it will require a big mess of recompiling the SDK.

@nyh

nyh commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

Nice! Does the Rust AWS SDK just let you add the parameters we invented, like VectorIndexes etc., without checking? That's nice - I was worried it will require a big mess of recompiling the SDK.

Answering myself, I see you used tricks like this:

let resp = client
        .query()
        .table_name(&table_name)
        .limit(2)
        .customize()
        .interceptor(JsonBodyInjectInterceptor::new([(
            "VectorSearch",
            vector_search,
        )]))
        .send()
        .await
        .expect("Query with VectorSearch should succeed");

This interceptor() thing is not pretty for end users (we'll probably need to modify the SDK to add new methods...) but certainly good enough for the tests! Very nice.

I don't know if you tried to actually run these tests with my latest code (scylladb/scylladb#29046), I hope that the CreateTable et al will already work, the Query certainly won't work entirely - I hope I'll get working tomorrow. Beyond the bugs I still have on the Scylla side, one obviously missing piece is on the vector store side - the ability to read an Alternator "list-of-decimal-numbers from an attribute in :attrs" instead of CQL's regular "vector of floats from a real column".

@m-szymon

Copy link
Copy Markdown
Collaborator Author

This interceptor() thing is not pretty for end users (we'll probably need to modify the SDK to add new methods...) but certainly good enough for the tests! Very nice.

I agree.

I don't know if you tried to actually run these tests with my latest code (scylladb/scylladb#29046), I hope that the CreateTable et al will already work.

I tried, but it didn't work.
VS can't get the dimensions of the target column - it tries to read it from schema, not index options:
https://github.com/scylladb/scylladb/pull/29046/changes/BASE..9765829566d7be4d63419bff84167c5464b93a38#r2950262327

@m-szymon

Copy link
Copy Markdown
Collaborator Author

I extended tests.
I expect create/delete index tests to pass with @QuerthDP current fixes - #394 (it did with my workarounds to VS).
Creating index with preexisting data is probably next to be fixed.
Then all the item editing tests depend on monitoring values from CDC.
And finally query tests.

@QuerthDP

Copy link
Copy Markdown
Member

I extended tests. I expect create/delete index tests to pass with @QuerthDP current fixes - #394 (it did with my workarounds to VS). Creating index with preexisting data is probably next to be fixed. Then all the item editing tests depend on monitoring values from CDC. And finally query tests.

I'm working on enabling the full scan and CDC reads for Alternator. As I noticed there's probably an issue with case sensitive Alternator table names - working on a fix within CDC driver as well.

@m-szymon

Copy link
Copy Markdown
Collaborator Author

I cannot request reviews, but it should be reviewed. @QuerthDP, @ewienik, @knowack1
The patch is added after @QuerthDP PR: #394
So consider only last 4 commits.

@QuerthDP

Copy link
Copy Markdown
Member

I cannot request reviews, but it should be reviewed. @QuerthDP, @ewienik, @knowack1 The patch is added after @QuerthDP PR: #394 So consider only last 4 commits.

@ewienik I think we should change this to allow at least Scylla org members to request the reviews.

@m-szymon

Copy link
Copy Markdown
Collaborator Author

I added some more tests - I add them as fixup! in case anyone already started review.
Some tests are failing - I report them in respective PRs: #394 and scylladb/scylladb#29046

My fixes to pass these test are in https://github.com/m-szymon/scylladb/commits/VS-fix-lwt/ and https://github.com/m-szymon/vector-store/tree/experimental-fix-alternator but they are not guaranteed to be correct.

I plan to add more tests regarding "Decimal" handling.

piodul added a commit to scylladb/scylladb that referenced this pull request Apr 17, 2026
This series adds support for vector search in Alternator based on the existing implementation in CQL.

The series adds APIs for `CreateTable` and `UpdateTable` to add or remove vector indexes to Alternator tables, `DescribeTable` to list them and check the indexing status, and `Query` to perform a vector search - which contacts the vector store for the actual ANN (approximate nearest neighbor) search.

Correct functionality of these features depend on some features of the the vector store, that were already done (see scylladb/vector-store#394).

This initial implementation is fully functional, and can already be useful, but we do not yet support all the features we hope to eventually support. Here are things that we have **not** done yet, and plan to do later in follow-up pull requests:

1. Support a new optimized vector type ("V") - in addition to the "list of numbers" type supported in this version.
2. Allow choosing a different similarity function when creating an index, by SimilarityFunction in VectorIndex definition.
3. Allow choosing quantization (f32/f16/bf16/i8/b1) to ask the vector index to compress stored vectors.
4. Support oversampling and rescoring, defined per-index and per-query.
5. Support HNSW tuning parameters — maximum_node_connections, construction_beam_width, search_beam_width.
6. Support pre-filtering over key columns, which are available at the vector store, by sending the filter to the vector store (translated from DynamoDB filter syntax to the vector's store's filter syntax). A decision still need to be made if this will use KeyConditionExpression or FilterExpression. This version supports only post-filtering (with `FilterExpression`).
7. Support projecting non-key attributes into the index (Projection=INCLUDE and Projection=ALL), and then 1. pre-filtering using these attributes, and 2. efficiently return these attributes (using Select=ALL_PROJECTED_ATTRIBUTES, which today returns just the key columns).
8. Optimize the performance of `Query`, which today is inefficient for Select=ALL_ATTRIBUTES because it serially retrieves the matching items one at a time.
9. Returning the similarity scores with the items (the design proposes ReturnVectorSearchSimilarity).
10. Add more vector-search-specific metrics, beyond the metric we already have counting Query requests. For example separate latency and request-count metrics for vector-search Queries (distinct from GSI/LSI queries), and a metric accumulating the total Limit (K) across all vector search queries.
11. Consider how (and if at all) we want to run the tests in test/alternator/test_vector.py that need the vector store in the CI. Currently they are skipped in CI and only run manually (with `test/alternator/run --vs test_vector`).
12. UpdateTable 'Update' operation to modify index parameters. Only some can be modified, e.g., Oversampling.
13. Support for "local index" (separate index for each partition).
14. Make sure that vector search and Streams can be enabled concurrently on the same table - both need CDC but we need to verify that one doesn't confuse the other or disables options that the other needs. We can only do this after we have Alternator Streams running on tablets (since vector store requires tablets).

Testing the new Alternator vector search end-to-end requires running both Scylla and the vector store together. We will have such end-to-end tests in the vector store repository (see scylladb/vector-store#392), but we also add in this pull request many end-to-end tests written in Python, that can be run with the command "test/alternator/run --vs test_vector.py". The "--vs" option tells the run script to run both Scylla and the vector store (currently assumed to be in `.../vector-store/target/release/vector-store`). About 65% of the tests in this pull request check supported syntax and error paths so can run without the vector store, while about 35% of the tests do perform actual Query operations and require the vector store to be running. Currently, the tests that do require the vector store will not get run by CI, but can be easily re-run manually with `test/alternator/run --vs test_vector.py`.

 In total, this series includes 78 functional tests in 2200 lines of Python code.

This series also includes documentation for the new Alternator feature and the new APIs introduced. You can see a more detailed design document here: https://docs.google.com/document/d/1cxLI7n-AgV5hhH1DTyU_Es8_f-t8Acql-1f58eQjZLY/edit

Two patches in this series split the huge alternator/executor.cc, after this series continued to grow it and it reached a whoppng 7,000 lines. These patches are just reorganization of code, no functional changes. But it's time that we finally do this (Refs #5783), we can't just continue to grow executor.cc with no end...

Closes #29046

* github.com:scylladb/scylladb:
  test/alternator: add option to "run" script to run with vector search
  alternator: document vector search
  test/alternator: fix retries in new_dynamodb_session
  test/alternator: test for allowed characters in attribute names
  test/alternator: tests for vector index support
  alternator, vector: add validation of non-finite numbers in Query
  alternator: Query: improve error message when VectorSearch is missing
  alternator: add per-table metrics for vector query
  alternator: clean up duplicated code
  alternator: fix default Select of Query
  alternator: split executor.cc even more
  alternator: split alternator/executor.cc
  alternator: validate vector index attribute values on write
  alternator: DescribeTable for vector index: add IndexStatus and Backfilling
  alternator: implement Query with a vector index
  alternator: fix bug in describe_multi_item()
  alternator: prevent adding GSI conflicting with a vector index
  alternator: implement UpdateTable with a vector index
  alternator: implement DescribeTable with a vector index
  alternator: implement CreateTable with a vector index
  alternator: reject empty attribute names
  cdc: fix on_pre_create_column_families to create CDC log for vector search
@QuerthDP

Copy link
Copy Markdown
Member

@m-szymon I think we shall proceed with this PR. You could extract the failing Decimal type tests to the other PR, but let's continue to try to merge the rest of Alternator tests as you introduced a really useful framework to implement them onto in this PR.

@nyh

nyh commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

@m-szymon I think we shall proceed with this PR. You could extract the failing Decimal type tests to the other PR, but let's continue to try to merge the rest of Alternator tests as you introduced a really useful framework to implement them onto in this PR.

I agree. I think this should be merged. As much as I like my own tests in Python (there are now 94 of them, and test_vector.py is the largest test file in test/alternator...), I think it's important to also have these tests in the laguage and framework which is easy to run and easy to understand for vector store developers. Also, if I understand correctly, unlike my Python tests (which don't run in CI), these Rusts ones do run in the vector store CI, right? That's important too.

About the failing tests for decimal keys - I'm a strong believer that if you write a test and discover it fails due to a bug, you should leave this test, marked with "xfail". You shouldn't just take it out of the test suite and cause it to be forgetten. These xfailing tests will be useful a week from now - or 5 years from now - when somebody will fix this bug. The tests will help the future developer understand the bug, or if that future developer will be you, it will help you remember what this bug is :-)

@swasik

swasik commented Apr 23, 2026

Copy link
Copy Markdown
Collaborator

FYI: Decimals fix is just being merged so we should be good to continue this @m-szymon.

@QuerthDP

QuerthDP commented Apr 23, 2026

Copy link
Copy Markdown
Member

FYI: Decimals fix is just being merged so we should be good to continue this @m-szymon.

We need to merge #416 before that. However having this test PR prioritized is crucial. It's a blocker for #420 as well.
AFAIK @m-szymon is working on rebasing this

@m-szymon

Copy link
Copy Markdown
Collaborator Author

FYI: Decimals fix is just being merged so we should be good to continue this @m-szymon.

But it was not the one in scylla that was blocking me.
I wanted this one #416 first, but now I am not sure it is correct.
So I will proceed without decimal keys for now, but I am still investigating some potential flakiness here.

@QuerthDP QuerthDP 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 addressing most of the previous comments. Looks better now.

Comment on lines +266 to +271
info!("Confirming arbitrary writes are accepted after index deletion");
ctx.put(
&Item::key(shape.pk, shape.sk, "pk", "c")
.attr(vec_attr, AttributeValue::S("not-a-vector".into())),
)
.await;

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.

Yes I meant the attribute other than vec_attr but if you think it's unnecessary let's skip that.

Comment on lines +297 to +372
// ---------------------------------------------------------------------------
// Test: Query with VectorSearch returns results in distance order
// ---------------------------------------------------------------------------

/// Creates an Alternator table with 5 items at known cosine distances from a
/// query vector, retrieves all of them via VectorSearch with Limit=5, and
/// asserts that the returned items are ordered by ascending cosine distance
/// (nearest first).
///
/// Alternator vector indexes always use **cosine** similarity (the default;
/// there is currently no way to select another metric via the Alternator API).
/// Cosine distance = 1 - cos(theta), so vectors pointing in the same direction as
/// the query vector are "nearest" regardless of magnitude.
#[framed]
async fn query_with_vector_search_multiple_results_ordering(actors: TestActors) {
info!("started");

let dataset = [
Item::new("Pk-Ord", AttributeValue::S("pk-nearest".into())).vec("Vec-Ord", [1.0, 0.0, 0.0]),
Item::new("Pk-Ord", AttributeValue::S("pk-near".into())).vec("Vec-Ord", [1.0, 0.1, 0.0]),
Item::new("Pk-Ord", AttributeValue::S("pk-mid".into())).vec("Vec-Ord", [1.0, 1.0, 0.0]),
Item::new("Pk-Ord", AttributeValue::S("pk-far".into())).vec("Vec-Ord", [0.0, 1.0, 0.0]),
Item::new("Pk-Ord", AttributeValue::S("pk-farthest".into()))
.vec("Vec-Ord", [-1.0, 0.0, 0.0]),
];

let ctx = TableContext::create_with_data(
&actors,
&super::TableShape {
table_prefix: "",
index_prefix: "",
pk: "Pk-Ord",
sk: None,
vec: Some("Vec-Ord"),
pk_type: super::ScalarAttributeType::S,
},
&dataset,
)
.await;

let expected_order: Vec<AttributeValue> = dataset
.iter()
.map(|i| i.0.get("Pk-Ord").expect("item has no Pk-Ord").clone())
.collect();

info!(
"Issuing Query with VectorSearch Limit=5 on '{}'",
ctx.table_name
);
let raw = ctx
.client
.query()
.table_name(&ctx.table_name)
.index_name(ctx.index.index.as_ref())
.limit(5)
.vector_search([1.0, 0.0, 0.0])
.send()
.await
.expect("Query with VectorSearch should succeed")
.items()
.to_vec();
let actual_order: Vec<AttributeValue> = raw
.iter()
.filter_map(|item| item.get("Pk-Ord"))
.cloned()
.collect();

assert_eq!(
actual_order, expected_order,
"Results should be ordered by ascending cosine distance from query vector"
);

ctx.done().await;

info!("finished");
}

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.

I assumed that for small dataset the result is deterministic, especially if limit >= size. I don't have proof that it is true, but there is something wrong if it is not.

There is indeed a serious problem in testing probabilistic solutions. We can never be sure about the real result, so each test checking that is inherently made flaky.
We have a serious problem with that in this repo (f.e. VECTOR-552), and it's struggling to deal with - checking if the test failure is really just a wrong index build configuration and not a serious problem.
We aim to add the exact search just for the tests, since we don't really care about the quality of probabilistic search to test the features. This will be checked by the benchmarks with much bigger datasets.

/// - items from the other partition key are absent,
/// - the correct number of items is returned.
#[framed]
async fn query_with_key_condition_expression(actors: TestActors) {

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.

I'd like to see this function registered, but ignored (skipped).
But as far as I know we don't have such case in Validator tests yet, so let it stay like that.
Just an idea for future improvements.

@m-szymon m-szymon left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think I addressed all remarks.

The build will fail as it requires this PR scylladb/e2etest-rs#1.

I also removed failing test - I will add it when we have xfail functionality: scylladb/e2etest-rs#2

As requested I reduced some comments.

@QuerthDP

Additional question: why some tests use TableContext while others don't? Maybe we could have it unified (at least for most similar cases)

TableContext is helper for managing test table with most typical setups.
If the test requires some specific setup, used only in that single test, which would require extending TableContext - I am not using it.

@nyh

Note that if I understand correctly, one of the patches fixes a bug related to items with missing vectors. Perhaps you should have a separate issue on this bug?

I thought that this count is used only in tests, but now I see it may we wider. I moved it to separate PR: #447

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I used wrong wording. Usearch returns error. And it is handled and generates warn.
I meant that such vector in general is ignored and considered it a correct behavior.
But it should be considered if we actually should have warn for such case.

fn remove(&self, primary_id: PrimaryId) -> anyhow::Result<()> {
Ok(self.inner.remove(primary_id.into()).map(|_| ())?)
fn remove(&self, primary_id: PrimaryId) -> anyhow::Result<usize> {
Ok(self.inner.remove(primary_id.into())?)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

But it is not an error. And it would trigger warn, when we actually fix the invalid entry.
Unless we keep information with timestamp that vector is invalid and was not added to index, in which case we will not need to try to remove it. But I think it is overkill.

Comment on lines +394 to +398
let removed = if sim.keys.write().unwrap().remove(&row_id) {
1
} else {
0
};

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, bool would be cleaner in this case

Comment on lines +1045 to +1048
Ok(0) => {}
Ok(_) => {
size.fetch_sub(1, Ordering::Relaxed);
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Both are not quite correct, when we used usize. I will use bool.

Comment thread crates/validator/src/alternator/mod.rs Outdated
/// The format is `Alt-Tbl_NNNNN` where `NNNNN` is a zero-padded counter.
/// Fixed length is important so that callers can compute exact total lengths
/// when composing table names (e.g. adding a prefix to hit the 192-char max).
pub(super) fn unique_alternator_table_name() -> String {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

true. fixed

Comment thread crates/validator/src/alternator/mod.rs Outdated
const SPECIAL_TABLE_PREFIX: &str = concat!(
"123-With.Hyphens_UPPER.MixedCase-",
"maxlen-pad.maxlen-pad.maxlen-pad.maxlen-pad.maxlen-pad.",
"maxlen-pad.maxlen-pad.maxlen-pad.maxlen-pad.maxlen-pad.",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

That was just some padding. I changed the approach to generate it at runtime.

Comment on lines +297 to +372
// ---------------------------------------------------------------------------
// Test: Query with VectorSearch returns results in distance order
// ---------------------------------------------------------------------------

/// Creates an Alternator table with 5 items at known cosine distances from a
/// query vector, retrieves all of them via VectorSearch with Limit=5, and
/// asserts that the returned items are ordered by ascending cosine distance
/// (nearest first).
///
/// Alternator vector indexes always use **cosine** similarity (the default;
/// there is currently no way to select another metric via the Alternator API).
/// Cosine distance = 1 - cos(theta), so vectors pointing in the same direction as
/// the query vector are "nearest" regardless of magnitude.
#[framed]
async fn query_with_vector_search_multiple_results_ordering(actors: TestActors) {
info!("started");

let dataset = [
Item::new("Pk-Ord", AttributeValue::S("pk-nearest".into())).vec("Vec-Ord", [1.0, 0.0, 0.0]),
Item::new("Pk-Ord", AttributeValue::S("pk-near".into())).vec("Vec-Ord", [1.0, 0.1, 0.0]),
Item::new("Pk-Ord", AttributeValue::S("pk-mid".into())).vec("Vec-Ord", [1.0, 1.0, 0.0]),
Item::new("Pk-Ord", AttributeValue::S("pk-far".into())).vec("Vec-Ord", [0.0, 1.0, 0.0]),
Item::new("Pk-Ord", AttributeValue::S("pk-farthest".into()))
.vec("Vec-Ord", [-1.0, 0.0, 0.0]),
];

let ctx = TableContext::create_with_data(
&actors,
&super::TableShape {
table_prefix: "",
index_prefix: "",
pk: "Pk-Ord",
sk: None,
vec: Some("Vec-Ord"),
pk_type: super::ScalarAttributeType::S,
},
&dataset,
)
.await;

let expected_order: Vec<AttributeValue> = dataset
.iter()
.map(|i| i.0.get("Pk-Ord").expect("item has no Pk-Ord").clone())
.collect();

info!(
"Issuing Query with VectorSearch Limit=5 on '{}'",
ctx.table_name
);
let raw = ctx
.client
.query()
.table_name(&ctx.table_name)
.index_name(ctx.index.index.as_ref())
.limit(5)
.vector_search([1.0, 0.0, 0.0])
.send()
.await
.expect("Query with VectorSearch should succeed")
.items()
.to_vec();
let actual_order: Vec<AttributeValue> = raw
.iter()
.filter_map(|item| item.get("Pk-Ord"))
.cloned()
.collect();

assert_eq!(
actual_order, expected_order,
"Results should be ordered by ascending cosine distance from query vector"
);

ctx.done().await;

info!("finished");
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

/// - items from the other partition key are absent,
/// - the correct number of items is returned.
#[framed]
async fn query_with_key_condition_expression(actors: TestActors) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Could be, but Rust doesn't like dead code.
And it would be basically moving whole files to separate commit, so I don't see much benefit.

Comment thread crates/validator/src/alternator/mod.rs Outdated
Comment on lines +482 to +485
) -> Result<
aws_sdk_dynamodb::operation::create_table::CreateTableOutput,
aws_sdk_dynamodb::error::SdkError<aws_sdk_dynamodb::operation::create_table::CreateTableError>,
> {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

In this form it is used only once - elsewhere it is automatically defined.
I think not worth creating an alias.

@m-szymon
m-szymon force-pushed the alternator_tests branch 3 times, most recently from 53df579 to 9924b16 Compare May 14, 2026 10:51
m-szymon added 6 commits May 14, 2026 13:17
Introduce the Alternator integration test suite with shared infrastructure
(TableShape, NAME_PATTERNS 2x2 matrix, TableContext) and tests for table
and index lifecycle operations: CreateTable, DescribeTable, DeleteTable,
and UpdateTable (create/delete vector index).
Adds LWT/Paxos code path coverage for VS indexing on Alternator writes,
in two layers.

New test suite `alternator_lwt` (`--alternator-write-isolation=always_use_lwt`):
Every write — including non-RMW PutItem and DeleteItem — goes through the
LWT/Paxos path in storage_proxy.cc.  Exercises PutItem, DeleteItem,
UpdateItem, and BatchWriteItem (put-only, mixed put+delete, delete-only).

LWT coverage added to the normal alternator suite (`only_rmw_uses_lwt`):
- conditional PutItem with ConditionExpression → LWT path
- conditional DeleteItem with ConditionExpression → LWT path
- conditional UpdateItem SET with ConditionExpression → LWT path
- new test `update_item_vector_element_operations`: element-level UpdateItem
  ops — SET #vec[i], REMOVE #vec[i], list_append, ADD #vec[i], fixing items
  with mixed-type or wrong-dimension vectors; ADD on a vector component
  triggers re-indexing via the LWT RMW path
Tests that Alternator correctly enforces authorization when
--alternator-enforce-authorization=true is set:
- wrong credentials yield UnrecognizedClientException
- a role with only CREATE ON ALL KEYSPACES can create a table with a
  vector index and write items (auto-granted MODIFY at CreateTable time)
- revoking ALTER from the creator role causes UpdateTable to return
  AccessDeniedException
- VS successfully indexes data written by a limited-permission role
@m-szymon
m-szymon force-pushed the alternator_tests branch from 9924b16 to 13cee25 Compare May 14, 2026 11:19
@m-szymon

Copy link
Copy Markdown
Collaborator Author

I reorganized registering tests, so alternator tests are split into separate TestCases.

@m-szymon
m-szymon requested review from QuerthDP and ewienik May 14, 2026 11:39

@QuerthDP QuerthDP 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.

This PR is really hard to review.
It takes hours to read and read again and fully understand what each function is responsible for.

Please consider splitting into small reviewable PRs. Once the utils get it, it will be really easy to review the tests.
As for now there is a whole bunch of comments, which is really annoying to search through which was done and how it was done. GitHub seems really not the best tool for that. I liked it more in the previous version where the comments sticked to the code. As for now I feel like only the first commit has them, the rest just disappears.

If you're afraid of the dead code. Please use the names with underscore prefix. That will be an straightforward indicator of what actually mattered, when all the PRs eventurally get merged and some functions might not be needed.
Let's split that, and then we could improve it eventually.

use super::resolve_table_names;
use super::unique_alternator_index_name;
use super::unique_alternator_table_name;
/// An SDK interceptor that captures the `VectorIndexes` extension field from

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: new line missing

use super::unique_alternator_index_name;
use super::unique_alternator_table_name;
/// An SDK interceptor that captures the `VectorIndexes` extension field from
/// the raw `DescribeTable` JSON response as a [`serde_json::Value`]. The

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: double space

use std::time::Duration;
use tracing::info;
use tracing::warn;
static TABLE_COUNTER: AtomicUsize = AtomicUsize::new(0);

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: missing newline

Comment on lines +115 to +126
/// # Example
/// ```ignore
/// client
/// .create_table()
/// // ...
/// .customize()
/// .interceptor(JsonBodyInjectInterceptor::new([
/// ("VectorIndexes", vector_indexes_json),
/// ]))
/// .send()
/// .await?;
/// ```

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.

Either don't introduce the code in docstrings or don't ignore it

Comment on lines +284 to +304
async fn wait_for_index_count(client: &HttpClient, index: &IndexInfo, expected_count: usize) {
common::wait_for(
|| async {
client
.index_status(&index.keyspace, &index.index)
.await
.is_ok_and(|resp| {
resp.status == httpapi::IndexStatus::Serving && resp.count == expected_count
})
},
format!(
"index '{}/{}' to report count {} at {}",
index.keyspace,
index.index,
expected_count,
client.url()
),
Duration::from_secs(60),
)
.await;
}

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.

This could be introduced as a common function. I think we're using it or something similar in other tests, don't we?

@QuerthDP

Copy link
Copy Markdown
Member

I reorganized registering tests, so alternator tests are split into separate TestCases.

Thanks! It looks lots better now in my opinion, and functionally it's faster since it's split into separate parralel CI runs.

@ewienik ewienik left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Consider splitting commits into several PRs - now they are too big. What about something like this:

PR1 - create_table, commits:

  1. create empty testcase for create_table
  2. add first test
  3. add second test
  4. etc...

PR2 - update_table, commits:

  1. create empty testcase for update_table
  2. add first test
  3. add second test
  4. etc...

PRx - next test cases

In this structure I can better focus on smaller changes.

@@ -0,0 +1,527 @@
/*
* Copyright 2026-present ScyllaDB
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: 1.1

use std::sync::Arc;
use std::sync::Mutex;
use tracing::info;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: use single use block, without empty line

use super::resolve_table_names;
use super::unique_alternator_index_name;
use super::unique_alternator_table_name;
/// An SDK interceptor that captures the `VectorIndexes` extension field from

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: add empty line before struct doc comment

/// [`read_after_deserialization`]: Intercept::read_after_deserialization
#[derive(Debug, Clone)]
struct VectorIndexesCaptureInterceptor {
captured: Arc<Mutex<Option<serde_json::Value>>>,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: consider use serde_json::Value

Comment on lines +22 to +26
use super::alternator_keyspace;
use super::make_clients;
use super::resolve_table_names;
use super::unique_alternator_index_name;
use super::unique_alternator_table_name;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

for better module visibility consider using alternator module name instead of super

use crate::alternator;

Then you can use alternator::make_clients, etc...
Then you can make functions shorter: alternator::unique_index_name instead unique_alternator_index_name

Consider using pattern module::function_name instead of importing function and use its name.

use std::time::Duration;
use tracing::info;
use tracing::warn;
static TABLE_COUNTER: AtomicUsize = AtomicUsize::new(0);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: add new line

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Consider removing alternator name from function names - as they seems redundant

@swasik

swasik commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

@m-szymon what is the status of this (apart from multiple conflicts)? could we schedule completing it after scylla FTS is merged?

@m-szymon

Copy link
Copy Markdown
Collaborator Author

@m-szymon what is the status of this (apart from multiple conflicts)? could we schedule completing it after scylla FTS is merged?

Only last commit from this PR is not merged yet and it is opened in #484.
The rest was merged in separate PRs: #452, #458, #459, #464, #466, #467, #468.

So I am closing this one.

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.

6 participants