Skip to content

vector-store: Split VsIndex stream into VsIndexModify and VsIndexSearch - #542

Merged
ewienik merged 3 commits into
scylladb:masterfrom
ewienik:vector-780-split-vsindex
Aug 7, 2026
Merged

vector-store: Split VsIndex stream into VsIndexModify and VsIndexSearch#542
ewienik merged 3 commits into
scylladb:masterfrom
ewienik:vector-780-split-vsindex

Conversation

@ewienik

@ewienik ewienik commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

This PR solves an issue with high search latency during massive vector
deletion from table. It divides VsIndex message stream into two: VsIndexModify
and VsIndexSearch. It gives priority to the VsIndexSearch.

The selection for ready messages is biased on VsIndexSearch. Tokio runtime uses
a fair scheduler and from experience it is visible that providing new search
requests is working in waves: first buffered then fully consumed. So we
shouldn't starve VsIndexModify stream.

One commit fixes unit tests after change in message priorities.

Fixes: VECTOR-780

@ewienik

ewienik commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

Changelog for bc4526b

  • rebase to master
range diff
1:  ebface6c2 ! 1:  a6c5f2595 vector-store: refactor VsIndex into Modify and Search
    @@ crates/vector-store/src/vs_index/usearch.rs: mod tests {
     +    use crate::vs_index::VsIndexSearchExt;
          use crate::worker;
          use mockall::predicate::*;
    -     use scylla::value::CqlValue;
    +     use rstest::rstest;
     @@ crates/vector-store/src/vs_index/usearch.rs: mod tests {
      
          fn add_concurrently(
2:  890343bf2 ! 2:  bc4526b18 tests: fix usearch::tests::add_or_replace_size_ann after prioritize search
    @@ crates/vector-store/src/vs_index/usearch.rs: mod tests {
     +        wait_for_count(&search, index_key.clone(), 1).await.unwrap();
          }
      
    -     #[tokio::test(flavor = "multi_thread")]
    +     #[rstest]
     @@ crates/vector-store/src/vs_index/usearch.rs: mod tests {
                  .returning(move |_| Some(index_id));
      

@ewienik
ewienik force-pushed the vector-780-split-vsindex branch from 890343b to bc4526b Compare August 6, 2026 13:31
@ewienik
ewienik marked this pull request as ready for review August 6, 2026 13:32

@Akvear Akvear left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If this doesn't actually starve VsIndexModify then it looks OK.

@ewienik

ewienik commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

Changelog for 35b11c6

  • refactor to master
range diff
1:  a6c5f2595 ! 1:  b6918c897 vector-store: refactor VsIndex into Modify and Search
    @@ crates/vector-store/src/engine.rs: use crate::node_state::NodeState;
      use std::sync::Arc;
      use std::sync::RwLock;
      use std::time::Duration;
    -@@ crates/vector-store/src/engine.rs: use tracing::trace;
    +@@ crates/vector-store/src/engine.rs: use tracing::info;
    + use tracing::trace;
      
    - type GetVsIndexKeysR = Vec<(IndexKey, crate::IndexOptionsVs)>;
      type AddIndexR = anyhow::Result<()>;
     -type GetVsIndexR = Option<(mpsc::Sender<VsIndex>, mpsc::Sender<DbIndex>)>;
     +type GetVsIndexR = Option<(mpsc::Sender<VsIndexSearch>, mpsc::Sender<DbIndex>)>;
      type GetFtsIndexR = Option<(mpsc::Sender<FtsIndex>, mpsc::Sender<DbIndex>)>;
      
    - pub(crate) enum Engine {
    + #[allow(clippy::enum_variant_names)]
     @@ crates/vector-store/src/engine.rs: async fn add_index_vs(ctx: AddIndexContext<'_>) -> anyhow::Result<()> {
              .metadata
              .vs()
    @@ crates/vector-store/src/engine.rs: async fn add_index_vs(ctx: AddIndexContext<'_
          Ok(())
     
      ## crates/vector-store/src/httproutes.rs ##
    -@@ crates/vector-store/src/httproutes.rs: use crate::SimilarityScore;
    +@@ crates/vector-store/src/httproutes.rs: use crate::SpaceType;
      use crate::distance;
      use crate::engine::Engine;
      use crate::engine::EngineExt;
    @@ crates/vector-store/src/indexes.rs: impl<I, D: std::fmt::Debug> std::fmt::Debug
      }
      
     -pub(crate) type VsIndexEntry = IndexEntry<VsIndex, VsIndexData>;
    + pub(crate) type FtsIndexEntry = IndexEntry<FtsIndex, FtsIndexData>;
     +pub(crate) type VsIndexEntry = IndexEntry<VsIndexSearch, VsIndexData>;
    - pub(crate) type FtsIndexEntry = IndexEntry<FtsIndex>;
      
      #[derive(Debug)]
    + pub(crate) struct VsIndexData {
     @@ crates/vector-store/src/indexes.rs: impl<I, D> IndexEntry<I, D> {
      
      impl VsIndexEntry {
2:  bc4526b18 = 2:  35b11c619 tests: fix usearch::tests::add_or_replace_size_ann after prioritize search

@ewienik
ewienik force-pushed the vector-780-split-vsindex branch from bc4526b to 35b11c6 Compare August 6, 2026 15:35
@ewienik

ewienik commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

Changelog for 9dabb04

  • update biased justification
range diff
1:  b6918c897 ! 1:  abaa4e8b4 vector-store: refactor VsIndex into Modify and Search
    @@ crates/vector-store/src/vs_index/mod.rs: use tokio::sync::mpsc;
     +    rx_modify: &mut mpsc::Receiver<VsIndexModify>,
     +) -> Option<Message> {
     +    tokio::select! {
    -+        // The order of the select branches is important. We want to prioritize
    -+        // search messages over modify messages. We shouldn't starve modify
    -+        // messages since tokio runtime uses a fair scheduler.
    ++        // The order of the select branches is important. We want to prioritize search messages
    ++        // over modify messages. We shouldn't starve modify messages since tokio runtime uses a
    ++        // fair scheduler. From observations, it is visible that providing new search requests is
    ++        // working in waves: first buffered then fully consumed.
     +        biased;
     +
     +        msg = rx_search.recv() => {
2:  35b11c619 = 2:  9dabb045f tests: fix usearch::tests::add_or_replace_size_ann after prioritize search

@ewienik
ewienik force-pushed the vector-780-split-vsindex branch from 35b11c6 to 9dabb04 Compare August 6, 2026 15:41
@QuerthDP

QuerthDP commented Aug 7, 2026

Copy link
Copy Markdown
Member

This PR solves an issue with high search latency during massive vector
deletion from table.

Any benchmarks on that?

@ewienik

ewienik commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

This PR solves an issue with high search latency during massive vector
deletion from table.

Any benchmarks on that?

benchmarks showed in: VECTOR-780

@QuerthDP

QuerthDP commented Aug 7, 2026

Copy link
Copy Markdown
Member

This PR solves an issue with high search latency during massive vector
deletion from table.

Any benchmarks on that?

benchmarks showed in: VECTOR-780

Thanks!

However, it's quite poorly explained on the graph.
I assume that the peak in latency is when running concurrent search and delete before the changes, then the break is some reload to the new version, and after no peak is shown while running the same concurrent search and delete. Is that correct?

@ewienik

ewienik commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

This PR solves an issue with high search latency during massive vector
deletion from table.

Any benchmarks on that?

benchmarks showed in: VECTOR-780

Thanks!

However, it's quite poorly explained on the graph. I assume that the peak in latency is when running concurrent search and delete before the changes, then the break is some reload to the new version, and after no peak is shown while running the same concurrent search and delete. Is that correct?

Yes, that's correct :-)

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

Looks promising but please take a look at a potential bug I described.
I think this is relevant and leads to a real panics even on production.

Comment thread crates/vector-store/src/indexes.rs
Comment thread crates/vector-store/src/vs_index/mod.rs Outdated
@ewienik

ewienik commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

Changelog for bf081a9

  • refactor select to check both arms for None
  • add commit for fixing condition when modify receiver drops before
    monitor_items actors
range diff
1:  abaa4e8b4 ! 1:  7b6c7af06 vector-store: refactor VsIndex into Modify and Search
    @@ crates/vector-store/src/vs_index/mod.rs: use tokio::sync::mpsc;
     +        // working in waves: first buffered then fully consumed.
     +        biased;
     +
    -+        msg = rx_search.recv() => {
    -+            msg.map(Message::Search)
    -+        }
    -+
    -+        msg = rx_modify.recv() => {
    -+            msg.map(Message::Modify)
    -+        }
    ++        Some(msg) = rx_search.recv() => Some(Message::Search(msg)),
    ++        Some(msg) = rx_modify.recv() => Some(Message::Modify(msg)),
    ++        else => None,
     +    }
     +}
     +
2:  9dabb045f = 2:  17105617f tests: fix usearch::tests::add_or_replace_size_ann after prioritize search
-:  --------- > 3:  bf081a9ec vector-store: refactor index actor to return error in case of missing receiver

@ewienik
ewienik force-pushed the vector-780-split-vsindex branch from 9dabb04 to bf081a9 Compare August 7, 2026 12:56
ewienik added 2 commits August 7, 2026 14:59
This commit solves an issue with high search latency during massive vector
deletion from table. It divides VsIndex message stream into two: VsIndexModify
and VsIndexSearch. It gives priority to the VsIndexSearch.

The selection for ready messages is biased on VsIndexSearch. Tokio runtime uses
a fair scheduler and from experience it is visible that providing new search
requests is working in waves: first buffered then fully consumed. So we
shouldn't starve VsIndexModify stream.
…earch

When we prioritize search over modify we need to wait a bit longer for remove
and insert to take place in usearch. This fix checks the size of the usearch
index after modification and before searching it.

The commit refactors waiting for specified index size.
@ewienik

ewienik commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

Changelog for ce4a828

  • revert moving line
range diff
1:  7b6c7af06 ! 1:  1a97a4796 vector-store: refactor VsIndex into Modify and Search
    @@ crates/vector-store/src/indexes.rs: impl<I, D: std::fmt::Debug> std::fmt::Debug
      }
      
     -pub(crate) type VsIndexEntry = IndexEntry<VsIndex, VsIndexData>;
    - pub(crate) type FtsIndexEntry = IndexEntry<FtsIndex, FtsIndexData>;
     +pub(crate) type VsIndexEntry = IndexEntry<VsIndexSearch, VsIndexData>;
    + pub(crate) type FtsIndexEntry = IndexEntry<FtsIndex, FtsIndexData>;
      
      #[derive(Debug)]
    - pub(crate) struct VsIndexData {
     @@ crates/vector-store/src/indexes.rs: impl<I, D> IndexEntry<I, D> {
      
      impl VsIndexEntry {
2:  17105617f = 2:  6aef7fb17 tests: fix usearch::tests::add_or_replace_size_ann after prioritize search
3:  bf081a9ec = 3:  ce4a828e2 vector-store: refactor index actor to return error in case of missing receiver

@ewienik
ewienik force-pushed the vector-780-split-vsindex branch from bf081a9 to ce4a828 Compare August 7, 2026 13:00
@ewienik
ewienik requested a review from QuerthDP August 7, 2026 13:01
Comment thread crates/vector-store/src/monitor_items.rs Outdated
Comment thread crates/vector-store/src/monitor_items.rs Outdated
… receiver

Index actors receivers could drop in case of db index drop. Therefore,
monitor_items actor should take care of such errors with communication to the
downstream actor and should stop task as it is an indicator that index is
dropped. This commit changes panic in actor communication into returning error
and refactor monitor_items actor to stop working in such scenario.
@ewienik

ewienik commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

Changelog for 9e984b4

  • refactor Result into IndexStatus
range diff
1:  1a97a4796 = 1:  1a97a4796 vector-store: refactor VsIndex into Modify and Search
2:  6aef7fb17 = 2:  6aef7fb17 tests: fix usearch::tests::add_or_replace_size_ann after prioritize search
3:  ce4a828e2 ! 3:  9e984b40e vector-store: refactor index actor to return error in case of missing receiver
    @@ crates/vector-store/src/fts_index/tantivy.rs: mod tests {
              // Dropping our own sender leaves only those clones alive, so `recv` returns `None` exactly
     
      ## crates/vector-store/src/monitor_items.rs ##
    +@@ crates/vector-store/src/monitor_items.rs: use tracing::debug;
    + use tracing::error;
    + use tracing::error_span;
    + 
    ++pub(crate) enum IndexStatus {
    ++    Live,
    ++    Dead,
    ++}
    ++
    ++impl From<anyhow::Result<()>> for IndexStatus {
    ++    fn from(result: anyhow::Result<()>) -> Self {
    ++        match result {
    ++            Ok(()) => IndexStatus::Live,
    ++            Err(_) => IndexStatus::Dead,
    ++        }
    ++    }
    ++}
    ++
    ++impl IndexStatus {
    ++    pub(crate) fn is_dead(&self) -> bool {
    ++        matches!(self, IndexStatus::Dead)
    ++    }
    ++}
    ++
    + pub(crate) trait IndexDispatch {
    +     fn add_vector(
    +         &self,
     @@ crates/vector-store/src/monitor_items.rs: pub(crate) trait IndexDispatch {
              _primary_id: PrimaryId,
              _vector: Vector,
              _in_progress: AsyncInProgress,
     -    ) -> impl Future<Output = ()> + Send {
    -+    ) -> impl Future<Output = anyhow::Result<()>> + Send {
    ++    ) -> impl Future<Output = IndexStatus> + Send {
              async move {
                  error!("ignoring add vector for an index that does not support it");
    -+            Ok(())
    ++            IndexStatus::Live
              }
          }
      
    @@ crates/vector-store/src/monitor_items.rs: pub(crate) trait IndexDispatch {
              _document: String,
              _in_progress: AsyncInProgress,
     -    ) -> impl Future<Output = ()> + Send {
    -+    ) -> impl Future<Output = anyhow::Result<()>> + Send {
    ++    ) -> impl Future<Output = IndexStatus> + Send {
              async move {
                  error!("ignoring add document for an index that does not support it");
    -+            Ok(())
    ++            IndexStatus::Live
              }
          }
      
    @@ crates/vector-store/src/monitor_items.rs: pub(crate) trait IndexDispatch {
              primary_id: PrimaryId,
              in_progress: AsyncInProgress,
     -    ) -> impl Future<Output = ()> + Send;
    -+    ) -> impl Future<Output = anyhow::Result<()>> + Send;
    ++    ) -> impl Future<Output = IndexStatus> + Send;
      
     -    fn remove_partition(&self, partition_id: PartitionId) -> impl Future<Output = ()> + Send;
     +    fn remove_partition(
     +        &self,
     +        partition_id: PartitionId,
    -+    ) -> impl Future<Output = anyhow::Result<()>> + Send;
    ++    ) -> impl Future<Output = IndexStatus> + Send;
      }
      
      impl IndexDispatch for mpsc::Sender<VsIndexModify> {
    @@ crates/vector-store/src/monitor_items.rs: impl IndexDispatch for mpsc::Sender<Vs
              in_progress: AsyncInProgress,
     -    ) {
     -        VsIndexModifyExt::add_vector(self, partition_id, primary_id, vector, in_progress).await;
    -+    ) -> anyhow::Result<()> {
    -+        VsIndexModifyExt::add_vector(self, partition_id, primary_id, vector, in_progress).await
    ++    ) -> IndexStatus {
    ++        VsIndexModifyExt::add_vector(self, partition_id, primary_id, vector, in_progress)
    ++            .await
    ++            .into()
          }
      
          async fn remove_value(
    @@ crates/vector-store/src/monitor_items.rs: impl IndexDispatch for mpsc::Sender<Vs
              primary_id: PrimaryId,
              in_progress: AsyncInProgress,
     -    ) {
    -+    ) -> anyhow::Result<()> {
    ++    ) -> IndexStatus {
              self.remove_vector(partition_id, primary_id, in_progress)
     -            .await;
     +            .await
    ++            .into()
          }
      
     -    async fn remove_partition(&self, partition_id: PartitionId) {
     -        VsIndexModifyExt::remove_partition(self, partition_id).await;
    -+    async fn remove_partition(&self, partition_id: PartitionId) -> anyhow::Result<()> {
    -+        VsIndexModifyExt::remove_partition(self, partition_id).await
    ++    async fn remove_partition(&self, partition_id: PartitionId) -> IndexStatus {
    ++        VsIndexModifyExt::remove_partition(self, partition_id)
    ++            .await
    ++            .into()
          }
      }
      
    @@ crates/vector-store/src/monitor_items.rs: impl IndexDispatch for mpsc::Sender<Ft
              in_progress: AsyncInProgress,
     -    ) {
     -        FtsIndexExt::add_document(self, primary_id, document, in_progress).await;
    -+    ) -> anyhow::Result<()> {
    -+        FtsIndexExt::add_document(self, primary_id, document, in_progress).await
    ++    ) -> IndexStatus {
    ++        FtsIndexExt::add_document(self, primary_id, document, in_progress)
    ++            .await
    ++            .into()
          }
      
          async fn remove_value(
    @@ crates/vector-store/src/monitor_items.rs: impl IndexDispatch for mpsc::Sender<Ft
              in_progress: AsyncInProgress,
     -    ) {
     -        self.remove_document(primary_id, in_progress).await;
    -+    ) -> anyhow::Result<()> {
    -+        self.remove_document(primary_id, in_progress).await
    ++    ) -> IndexStatus {
    ++        self.remove_document(primary_id, in_progress).await.into()
          }
      
     -    async fn remove_partition(&self, _partition_id: PartitionId) {}
    -+    async fn remove_partition(&self, _partition_id: PartitionId) -> anyhow::Result<()> {
    -+        Ok(())
    ++    async fn remove_partition(&self, _partition_id: PartitionId) -> IndexStatus {
    ++        IndexStatus::Live
     +    }
      }
      
    @@ crates/vector-store/src/monitor_items.rs: where
                              match db_row.operation {
                                  DbIndexedOperation::Upsert(values) => {
     -                                upsert(&table, &index, primary_key, values, in_progress, &metrics, &key).await;
    -+                                if let Err(err) = upsert(&table, &index, primary_key, values, in_progress, &metrics, &key).await {
    -+                                    error!("unable to upsert values in index {key:?}: {err:?}");
    ++                                if upsert(&table, &index, primary_key, values, in_progress, &metrics, &key).await.is_dead() {
    ++                                    error!("Index for {key:?} disappeared while processing upsert");
     +                                    break;
     +                                }
                                  }
                                  DbIndexedOperation::Delete(timestamp) => {
     -                                delete(&table, &index, primary_key, timestamp, in_progress, &metrics, &key).await;
    -+                                if let Err(err) = delete(&table, &index, primary_key, timestamp, in_progress, &metrics, &key).await {
    -+                                    error!("unable to delete values in index {key:?}: {err:?}");
    ++                                if delete(&table, &index, primary_key, timestamp, in_progress, &metrics, &key).await.is_dead() {
    ++                                    error!("Index for {key:?} disappeared while processing delete");
     +                                    break;
     +                                }
                                  }
    @@ crates/vector-store/src/monitor_items.rs: async fn upsert<I: IndexDispatch>(
          metrics: &Metrics,
          index_key: &IndexKey,
     -) {
    -+) -> anyhow::Result<()> {
    ++) -> IndexStatus {
          let Ok(operations) = table
              .write()
              .unwrap()
    @@ crates/vector-store/src/monitor_items.rs: async fn upsert<I: IndexDispatch>(
              })
          else {
     -        return;
    -+        return Ok(());
    ++        return IndexStatus::Live;
          };
     -    process_operations(operations, index, in_progress, metrics, index_key).await;
     +    process_operations(operations, index, in_progress, metrics, index_key).await
    @@ crates/vector-store/src/monitor_items.rs: async fn delete<I: IndexDispatch>(
          metrics: &Metrics,
          index_key: &IndexKey,
     -) {
    -+) -> anyhow::Result<()> {
    ++) -> IndexStatus {
          let Ok(operations) = table
              .write()
              .unwrap()
    @@ crates/vector-store/src/monitor_items.rs: async fn delete<I: IndexDispatch>(
              })
          else {
     -        return;
    -+        return Ok(());
    ++        return IndexStatus::Live;
          };
     -    process_operations(operations, index, in_progress, metrics, index_key).await;
     +    process_operations(operations, index, in_progress, metrics, index_key).await
    @@ crates/vector-store/src/monitor_items.rs: async fn process_operations<I: IndexDi
          metrics: &Metrics,
          index_key: &IndexKey,
     -) {
    -+) -> anyhow::Result<()> {
    ++) -> IndexStatus {
          let in_progress = &mut in_progress;
          for operation in operations.into_iter() {
              match operation {
     @@ crates/vector-store/src/monitor_items.rs: async fn process_operations<I: IndexDispatch>(
    +                 is_update,
    +             } => {
                      let op_label = if is_update { OP_UPDATE } else { OP_INSERT };
    -                 index
    +-                index
    ++                if index
                          .add_vector(partition_id, primary_id, vector, in_progress.take())
     -                    .await;
    -+                    .await?;
    ++                    .await
    ++                    .is_dead()
    ++                {
    ++                    return IndexStatus::Dead;
    ++                }
                      metrics
                          .modified
                          .with_label_values(&[
     @@ crates/vector-store/src/monitor_items.rs: async fn process_operations<I: IndexDispatch>(
    +                 is_update,
    +             } => {
                      let op_label = if is_update { OP_UPDATE } else { OP_INSERT };
    -                 index
    +-                index
    ++                if index
                          .add_document(partition_id, primary_id, document, in_progress.take())
     -                    .await;
    -+                    .await?;
    ++                    .await
    ++                    .is_dead()
    ++                {
    ++                    return IndexStatus::Dead;
    ++                }
                      metrics
                          .modified
                          .with_label_values(&[
     @@ crates/vector-store/src/monitor_items.rs: async fn process_operations<I: IndexDispatch>(
    +                 primary_id,
    +                 partition_id,
                  } => {
    -                 index
    +-                index
    ++                if index
                          .remove_value(partition_id, primary_id, AsyncInProgress::None)
     -                    .await;
    -+                    .await?;
    ++                    .await
    ++                    .is_dead()
    ++                {
    ++                    return IndexStatus::Dead;
    ++                }
                  }
                  Operation::RemoveValue {
                      primary_id,
    -@@ crates/vector-store/src/monitor_items.rs: async fn process_operations<I: IndexDispatch>(
    +                 partition_id,
                  } => {
    -                 index
    +-                index
    ++                if index
                          .remove_value(partition_id, primary_id, in_progress.take())
     -                    .await;
    -+                    .await?;
    ++                    .await
    ++                    .is_dead()
    ++                {
    ++                    return IndexStatus::Dead;
    ++                }
                      metrics
                          .modified
                          .with_label_values(&[
    @@ crates/vector-store/src/monitor_items.rs: async fn process_operations<I: IndexDi
                  }
                  Operation::RemovePartition { partition_id } => {
     -                index.remove_partition(partition_id).await;
    -+                index.remove_partition(partition_id).await?;
    ++                if index.remove_partition(partition_id).await.is_dead() {
    ++                    return IndexStatus::Dead;
    ++                }
                  }
              }
          }
      
          metrics.mark_dirty(index_key.keyspace().as_ref(), index_key.index().as_ref());
    -+    Ok(())
    ++    IndexStatus::Live
      }
      
      #[cfg(test)]

@ewienik
ewienik force-pushed the vector-780-split-vsindex branch from ce4a828 to 9e984b4 Compare August 7, 2026 14:07
@ewienik
ewienik requested a review from QuerthDP August 7, 2026 14:08

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

Looks better now thanks

Comment thread crates/vector-store/src/monitor_items.rs
@ewienik
ewienik enabled auto-merge August 7, 2026 14:17
@ewienik
ewienik added this pull request to the merge queue Aug 7, 2026
Merged via the queue into scylladb:master with commit e0d7b09 Aug 7, 2026
44 checks passed
@ewienik
ewienik deleted the vector-780-split-vsindex branch August 7, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants