Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7072ef7
types: add Schema newtype for logical store namespacing
gregorian-09 Jun 12, 2026
264c9fc
types: add Schema newtype for logical store namespacing
gregorian-09 Jun 12, 2026
41b05d8
db: fix type inference and use existing.current.clone() in nested sch…
gregorian-09 Jun 12, 2026
2b98e7a
ai/engine: refactor AIStoreHandler to use nested Schema maps
gregorian-09 Jun 12, 2026
0bb339e
ai: update operations and server handler to pass default schema
gregorian-09 Jun 12, 2026
8297ea3
types(build): preserve schema.rs from build script deletion
gregorian-09 Jun 12, 2026
02f9233
fix: remove schema parameter from all store handler methods
gregorian-09 Jun 12, 2026
f93b77b
feat: wire schema through protobuf, add DropSchema RPC
gregorian-09 Jun 13, 2026
e27be00
fix: count stores not schemas in purge_stores; add docs, tests, SDK s…
gregorian-09 Jun 14, 2026
511105f
style: format regenerated SDK stubs to pass CI lint checks
gregorian-09 Jun 15, 2026
cd37489
feat: add persistence migration from flat to nested schema format
gregorian-09 Jun 15, 2026
793f61a
fix: redundant closure in AI store migration, same pattern as DB
gregorian-09 Jun 16, 2026
5692f36
feat: add versioned persistence and fix Schema panic on empty string
gregorian-09 Jun 16, 2026
62fe152
fix: clippy redundant closure warnings, drop build_fixed.py
gregorian-09 Jun 16, 2026
fe67045
chore: regenerate gRPC stubs to match CI formatting
gregorian-09 Jun 16, 2026
62bd9fd
fix: add missing schema field in image-search example
gregorian-09 Jun 16, 2026
471be43
fix: conditionally include gtag only when G_TRACKING_ID is set
gregorian-09 Jun 16, 2026
449d4ba
feat: add V2 snapshot fixtures and DB migration tests
gregorian-09 Jun 16, 2026
ac66529
fix: apply cargo fmt to migration test files
gregorian-09 Jun 16, 2026
8e0bc95
fix: add fallback for unversioned schema-nested persistence format (V1n)
gregorian-09 Jun 16, 2026
c9c00a9
fix: scope purge_stores to public schema only
gregorian-09 Jun 17, 2026
1d0f647
rename: AiStoresV1Nested to AiStoresV2 and DbStoresV1Nested to DbStor…
gregorian-09 Jun 17, 2026
0e892d5
fix: scope get to default schema only, add schema param to get_store
gregorian-09 Jun 17, 2026
b8843bc
fix: use string-based serde for NodeId and LayerIndex for JSON map ke…
gregorian-09 Jun 17, 2026
18f8a82
feat: make purge_stores schema-aware, add schema to AiStoreInfo
gregorian-09 Jun 18, 2026
41be2d8
fix: revert to custom string-based serde for StoreKeyId, LayerIndex, …
gregorian-09 Jun 18, 2026
e11a4c5
fix: align schema persistence behavior
gregorian-09 Jun 19, 2026
d00ea7c
fix: regenerate Python stubs after proto field renumbering
gregorian-09 Jun 19, 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
1 change: 1 addition & 0 deletions ahnlich/ai/src/engine/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod ai;
pub mod operations;
pub mod store;
pub mod versioned;
59 changes: 48 additions & 11 deletions ahnlich/ai/src/engine/operations.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{collections::HashMap, sync::Arc};

use ahnlich_client_rs::db::DbClient;
use ahnlich_types::ai::query::DropSchema as AiDropSchema;
use ahnlich_types::{
ai::{
models::AiModel,
Expand Down Expand Up @@ -28,6 +29,7 @@ use ahnlich_types::{
In, Predicate, PredicateCondition, predicate::Kind as PredicateKind,
predicate_condition::Kind,
},
schema::Schema,
};
use itertools::Itertools;
use rayon::prelude::*;
Expand Down Expand Up @@ -90,6 +92,13 @@ pub async fn create_store(
predicates.push(AHNLICH_AI_ONE_TO_MANY_INDEX_META_KEY.to_string());
}

let schema = match &params.schema {
Some(s) => {
Schema::try_new(s.clone()).map_err(|e| AIProxyError::InvalidArgument(e.to_owned()))?
}
None => Schema::default(),
};

require_db_client(db_client)?
.create_store(
DbCreateStore {
Expand All @@ -98,6 +107,7 @@ pub async fn create_store(
create_predicates: predicates,
non_linear_indices: params.non_linear_indices,
error_if_exists: params.error_if_exists,
schema: Some(schema.to_string()),
},
parent_id,
)
Expand All @@ -107,6 +117,7 @@ pub async fn create_store(
StoreName {
value: params.store,
},
&schema,
query_model,
index_model,
params.error_if_exists,
Expand Down Expand Up @@ -353,6 +364,12 @@ pub async fn drop_store(
let store_name = StoreName {
value: params.store,
};
let schema = match &params.schema {
Some(s) => {
Schema::try_new(s.clone()).map_err(|e| AIProxyError::InvalidArgument(e.to_owned()))?
}
None => Schema::default(),
};

if store_handler.get(&store_name).is_ok()
&& let Some(db_client) = db_client
Expand All @@ -362,13 +379,14 @@ pub async fn drop_store(
DbDropStore {
store: store_name.value.clone(),
error_if_not_exists: params.error_if_not_exists,
schema: Some(schema.to_string()),
},
parent_id,
)
.await?;
}

let dropped = store_handler.drop_store(store_name, params.error_if_not_exists)?;
let dropped = store_handler.drop_store(store_name, &schema, params.error_if_not_exists)?;
Ok(Del {
deleted_count: dropped as u64,
})
Expand All @@ -380,19 +398,14 @@ pub async fn purge_stores(
_params: PurgeStores,
parent_id: Option<String>,
) -> Result<Del, Status> {
let store_names: Vec<StoreName> = store_handler
.list_stores()
.into_iter()
.map(|store| StoreName { value: store.name })
.collect();

if let Some(db_client) = db_client {
for store_name in &store_names {
for (schema, store_name) in store_handler.all_store_names_by_schema() {
db_client
.drop_store(
DbDropStore {
store: store_name.value.clone(),
store: store_name.value,
error_if_not_exists: false,
schema: Some(schema),
},
parent_id.clone(),
)
Expand All @@ -408,10 +421,19 @@ pub async fn purge_stores(
pub async fn list_stores(
store_handler: &AIStoreHandler,
db_client: Option<Arc<DbClient>>,
_params: ListStores,
params: ListStores,
parent_id: Option<String>,
) -> Result<StoreList, Status> {
let mut stores: Vec<AiStoreInfo> = store_handler.list_stores().into_iter().sorted().collect();
let filter_schema = params
.schema
.as_ref()
.filter(|s| !s.is_empty())
.map(|s| Schema::new(s.clone()));
let mut stores: Vec<AiStoreInfo> = store_handler
.list_stores(filter_schema.as_ref())
.into_iter()
.sorted()
.collect();

if let Some(db_client) = db_client
&& let Ok(db_store_list) = db_client.list_stores(parent_id).await
Expand Down Expand Up @@ -439,3 +461,18 @@ pub async fn list_stores(

Ok(StoreList { stores })
}

pub async fn drop_schema(
store_handler: &AIStoreHandler,
_db_client: Option<Arc<DbClient>>,
params: AiDropSchema,
_parent_id: Option<String>,
) -> Result<Del, Status> {
let schema =
Schema::try_new(params.schema).map_err(|e| AIProxyError::InvalidArgument(e.to_owned()))?;

let dropped = store_handler.drop_schema(&schema)?;
Ok(Del {
deleted_count: dropped as u64,
})
}
Loading