use uuid::Uuid;
use crate::api::tasks::{
TaskDefinition, TaskReadTarget, TaskReadTargetLatestOnBranch, VectorIndexBuildMode,
VectorIndexRefreshDefinition,
};
use crate::catalog_types::ProjectBranchId;
use crate::{Error, Project, ResourceAddress, Run, Snapshot, TaskHandle};
const VECTOR_INDEX_KIND: &str = "vector-index";
#[derive(Clone)]
pub struct VectorIndex {
project: Project,
branch_id: Option<ProjectBranchId>,
resource_id: Uuid,
version_id: Uuid,
}
impl Project {
pub async fn vector_index(&self, branch: &str, path: &str) -> Result<VectorIndex, Error> {
self.branch(branch)
.await?
.snapshot()
.vector_index(path)
.await
}
}
impl Snapshot {
pub async fn vector_index(&self, path: &str) -> Result<VectorIndex, Error> {
let address = path.parse::<ResourceAddress>()?;
if address.reference().is_some() {
return Err(Error::invalid(
"select the Vector Index's branch with the snapshot, not an `@` reference",
));
}
let resource = self.resource_at_path(address.path()).await?;
if resource.descriptor.kind.0 != VECTOR_INDEX_KIND {
return Err(Error::invalid(format!("`{path}` is not a Vector Index")));
}
Ok(VectorIndex {
project: self.project.clone(),
branch_id: self.branch_id,
resource_id: resource.descriptor.resource_id.as_uuid(),
version_id: resource.version_id.as_uuid(),
})
}
}
impl VectorIndex {
pub fn resource_id(&self) -> Uuid {
self.resource_id
}
pub fn version_id(&self) -> Uuid {
self.version_id
}
pub async fn refresh(
&self,
mode: VectorIndexBuildMode,
run: Run,
) -> Result<Option<TaskHandle>, Error> {
let branch_id = self.branch_id.ok_or_else(|| {
Error::invalid("refreshing a Vector Index needs a branch snapshot, not an exact commit")
})?;
let read = self
.project
.client
.vector_indexes()
.read_version(self.resource_id, self.version_id)
.await?;
let source_resource_id =
read.definition
.source_resource_id
.parse::<Uuid>()
.map_err(|_| {
Error::Protocol("the Vector Index's source is not a resource ID".into())
})?;
let definition = TaskDefinition::VectorIndexRefresh(VectorIndexRefreshDefinition {
read_target: TaskReadTarget::LatestOnBranch(TaskReadTargetLatestOnBranch {
branch_id: branch_id.as_uuid(),
}),
vector_index_id: self.resource_id,
vector_index_resource_id: self.resource_id,
source_resource_id,
mode,
latest: None,
});
self.project.submit_task(definition, None, run).await
}
}