Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
542b8c0
feat(storage): add vector data column family
happy-v587 Jul 19, 2026
3b309f6
feat(storage): add vector codecs
happy-v587 Jul 19, 2026
e822cab
feat(storage): persist vector set members
happy-v587 Jul 19, 2026
6837573
feat(storage): add flat vector similarity search
happy-v587 Jul 19, 2026
0152520
feat(storage): route and clean up vector sets
happy-v587 Jul 19, 2026
f55e74e
feat(cmd): add redis vector set commands
happy-v587 Jul 19, 2026
53ee9b0
fix(resp): downgrade vector scores for resp2
happy-v587 Jul 19, 2026
e02d043
fix(resp): encode nulls with native protocol type
happy-v587 Jul 19, 2026
e0d72be
test: cover redis vector set commands
happy-v587 Jul 19, 2026
dfd841f
test: skip vector set commands when server is unavailable
happy-v587 Jul 20, 2026
ede10cd
test: use unique test db path helpers in vector storage tests
happy-v587 Jul 23, 2026
049f9c0
refactor(storage): adapt vector set to engine removal
happy-v587 Jul 25, 2026
05148c0
docs: split cargo test filters and specify monotonic vector generation
happy-v587 Jul 25, 2026
20a5b8b
fix(vector): prevent stale members and protocol regressions
happy-v587 Jul 25, 2026
5e0e972
feat(vector): enable raft cluster mode and add metric/search abstract…
happy-v587 Jul 26, 2026
1ffceef
fix(cmd): keep MODULE_NO_CLUSTER flag definition
happy-v587 Jul 26, 2026
4ce0aed
refactor(vector,resp): address CodeRabbit review comments on PR #356
happy-v587 Jul 26, 2026
c3a9d78
Merge branch 'lh/feat/redis-vector' into feat/redis-vector
happy-v587 Jul 26, 2026
ea4eb2a
refactor(resp): inline encode_resp_data_inner into encode_resp_data
happy-v587 Jul 27, 2026
4bbe201
Merge remote-tracking branch 'origin/main' into feat/redis-vector
happy-v587 Jul 27, 2026
5a35356
feat(vector): add quantization framework (NOQUANT/BIN/Q8)
happy-v587 Jul 27, 2026
d65d7fa
feat(vector): parse VADD options and split per-command parsing
happy-v587 Jul 27, 2026
b9edac1
fix(vector): enforce phase one protocol semantics
happy-v587 Jul 28, 2026
9f1e37e
feat: extend vector lifecycle and admin capabilities
happy-v587 Jul 31, 2026
36b8e12
merge: resolve origin/main conflicts
happy-v587 Jul 31, 2026
24ce43b
Merge remote-tracking branch 'origin/main' into HEAD
happy-v587 Aug 2, 2026
61c30cc
fix: address vector PR review and CI failures
happy-v587 Aug 2, 2026
f3af349
fix: tombstone vector sets on DEL
happy-v587 Aug 2, 2026
f1f8d75
test: use public vector metadata assertions
happy-v587 Aug 2, 2026
b0db91f
fix: harden snapshot tests on Windows
happy-v587 Aug 2, 2026
6d57a5b
fix: avoid dynamic command gate allocations
happy-v587 Aug 2, 2026
8c294ea
test: cover vector gate precedence
happy-v587 Aug 2, 2026
b8d8735
merge: resolve origin/main conflicts
happy-v587 Aug 2, 2026
c16c3ef
fix(cmd): avoid zero-sized requirepass providers
happy-v587 Aug 2, 2026
9a446c5
test(cmd): cover hello provider storage
happy-v587 Aug 2, 2026
e8c8faf
fix(storage): avoid zero-sized cache callbacks
happy-v587 Aug 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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 29 additions & 1 deletion src/cmd/src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,29 @@ use storage::storage::Storage;

use crate::{AclCategory, Cmd, CmdFlags, CmdMeta, impl_cmd_clone_box, impl_cmd_meta};

/// INFO VECTOR section: the Phase 1 index kind plus the FLAT query counters.
/// vector_sets / vector_elements are omitted on purpose: counting them needs
/// a full keyspace scan and INFO must stay O(1).
fn vector_section(storage: &Storage) -> String {
let metrics = storage.vector_metrics();
format!(
"# Vector\r\n\
index-kind:flat\r\n\
vector_flat_queries_total:{}\r\n\
vector_flat_query_timeouts_total:{}\r\n\
vector_flat_query_errors_total:{}\r\n\
vector_search_capacity_rejected_total:{}\r\n\
vector_flat_query_duration_micros_total:{}\r\n\
vector_flat_query_duration_count:{}\r\n",
metrics.flat_queries_total,
metrics.flat_query_timeouts_total,
metrics.flat_query_errors_total,
metrics.capacity_rejected_total,
metrics.flat_query_duration_micros_total,
metrics.flat_query_duration_count,
)
}

/// INFO command - Show server information including cluster status
#[derive(Clone, Default)]
pub struct InfoCmd {
Expand Down Expand Up @@ -54,7 +77,7 @@ impl Cmd for InfoCmd {
true
}

fn do_cmd(&self, client: &Client, _storage: Arc<Storage>) {
fn do_cmd(&self, client: &Client, storage: Arc<Storage>) {
let section = if client.argv().len() > 1 {
String::from_utf8_lossy(&client.argv()[1]).to_lowercase()
} else {
Expand All @@ -69,6 +92,9 @@ impl Cmd for InfoCmd {
info.push_str("cluster_enabled:0\r\n");
info.push_str("cluster_state:disabled\r\n");
}
"vector" => {
info.push_str(&vector_section(&storage));
}
"server" | "default" => {
info.push_str("# Server\r\n");
info.push_str("redis_version:7.0.0\r\n");
Expand All @@ -95,6 +121,8 @@ impl Cmd for InfoCmd {
info.push_str("\r\n# Cluster\r\n");
info.push_str("cluster_enabled:0\r\n");
info.push_str("cluster_state:disabled\r\n");
info.push_str("\r\n");
info.push_str(&vector_section(&storage));
}
}
_ => {
Expand Down
17 changes: 16 additions & 1 deletion src/cmd/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ use crate::{impl_cmd_clone_box, impl_cmd_meta};

pub type RequirepassProvider = Arc<dyn Fn() -> Option<String> + Send + Sync>;

fn no_requirepass() -> Option<String> {
None
}

pub(crate) fn no_requirepass_provider() -> RequirepassProvider {
Arc::new(no_requirepass as fn() -> Option<String>)
}

#[derive(Clone)]
pub struct AuthCmd {
meta: CmdMeta,
Expand All @@ -43,7 +51,7 @@ impl Default for AuthCmd {
acl_category: AclCategory::CONNECTION,
..Default::default()
},
requirepass_provider: Arc::new(|| None),
requirepass_provider: no_requirepass_provider(),
}
}
}
Expand Down Expand Up @@ -223,4 +231,11 @@ mod tests {
let cmd = AuthCmd::default();
assert!(cmd.has_flag(CmdFlags::NO_AUTH));
}

#[test]
fn default_requirepass_provider_has_nonzero_trait_object_data_size() {
let cmd = AuthCmd::default();

assert_ne!(std::mem::size_of_val(cmd.requirepass_provider.as_ref()), 0);
}
}
10 changes: 9 additions & 1 deletion src/cmd/src/hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use resp::{CommandType, HelloAuthResult, RespCommand, RespData, RespError};
use storage::storage::Storage;
use subtle::ConstantTimeEq;

use crate::auth::no_requirepass_provider;
use crate::{
AclCategory, Cmd, CmdFlags, CmdMeta, RequirepassProvider, impl_cmd_clone_box, impl_cmd_meta,
};
Expand All @@ -43,7 +44,7 @@ impl Default for HelloCmd {
acl_category: AclCategory::CONNECTION | AclCategory::FAST,
..Default::default()
},
requirepass_provider: Arc::new(|| None),
requirepass_provider: no_requirepass_provider(),
}
}
}
Expand Down Expand Up @@ -226,4 +227,11 @@ mod tests {

assert_eq!(client.name().as_slice(), b"my-client");
}

#[test]
fn default_requirepass_provider_has_nonzero_trait_object_data_size() {
let cmd = HelloCmd::default();

assert_ne!(std::mem::size_of_val(cmd.requirepass_provider.as_ref()), 0);
}
}
1 change: 1 addition & 0 deletions src/cmd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ pub mod sunionstore;
pub mod table;
pub mod ttl;
pub mod type_cmd;
pub mod vector;
pub mod zadd;
pub mod zcard;
pub mod zcount;
Expand Down
3 changes: 2 additions & 1 deletion src/cmd/src/substr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ mod tests {
use storage::{StorageOptions, safe_cleanup_test_db, unique_test_db_path};

use super::*;
use crate::auth::no_requirepass_provider;
use crate::table::create_command_table;

struct TestStream;
Expand Down Expand Up @@ -143,7 +144,7 @@ mod tests {
b"-100".to_vec(),
]);

let command_table = create_command_table(Arc::new(|| None));
let command_table = create_command_table(no_requirepass_provider());
command_table
.get("substr")
.expect("SUBSTR should be publicly registered")
Expand Down
Loading
Loading