use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GenericResponse {
pub success: bool,
pub message: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
pub enum StorageBackendType {
DoesNotExist = -1,
File = 0,
S3 = 1,
}
impl<'de> Deserialize<'de> for StorageBackendType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = i32::deserialize(deserializer)?;
match value {
-1 => Ok(StorageBackendType::DoesNotExist),
1 => Ok(StorageBackendType::File),
2 => Ok(StorageBackendType::S3),
_ => Err(serde::de::Error::custom(format!(
"Invalid storage backend type: {}",
value
))),
}
}
}
impl Serialize for StorageBackendType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_i32(*self as i32)
}
}
impl StorageBackendType {
pub fn as_str(&self) -> &'static str {
match self {
StorageBackendType::File => "disk",
StorageBackendType::S3 => "s3",
StorageBackendType::DoesNotExist => "unknown",
}
}
pub fn is_valid(&self) -> bool {
matches!(self, StorageBackendType::File | StorageBackendType::S3)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
pub enum AttrType {
Int64 = 0,
Float64 = 1,
String = 2,
Bool = 3,
}
impl AttrType {
pub fn as_str(&self) -> &'static str {
match self {
AttrType::Int64 => "int64",
AttrType::Float64 => "float64",
AttrType::String => "string",
AttrType::Bool => "bool",
}
}
}
impl<'de> Deserialize<'de> for AttrType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = i32::deserialize(deserializer)?;
match value {
0 => Ok(AttrType::Int64),
1 => Ok(AttrType::Float64),
2 => Ok(AttrType::String),
3 => Ok(AttrType::Bool),
_ => Err(serde::de::Error::custom(format!(
"Invalid attribute type: {}",
value
))),
}
}
}
impl Serialize for AttrType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_i32(*self as i32)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetadataColumnSchema {
pub name: String,
#[serde(rename = "type")]
pub attr_type: AttrType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Collection {
pub name: String,
pub is_loaded: bool,
pub fields: Option<Vec<String>>,
pub searchable_fields: Option<Vec<String>>,
#[serde(default)]
pub metadata: Option<Vec<MetadataColumnSchema>>,
pub has_metadata_enabled: bool,
pub no_reference_storage: bool,
pub storage_type: StorageBackendType,
pub reference_storage_type: StorageBackendType,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_pq_enabled: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetadataSupportInfo {
pub support_metadata: bool,
pub name: String,
#[serde(rename = "type")]
pub storage_type: StorageBackendType,
pub is_default: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListCollectionsResponse {
pub success: bool,
pub message: String,
pub data: Vec<Collection>,
pub metadata_info: Vec<MetadataSupportInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddCollectionRequest {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub no_reference_storage: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub has_metadata_storage: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub storage_type: Option<StorageBackendType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reference_storage_type: Option<StorageBackendType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub enable_pq: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RecordData {
pub id: String,
pub expiry: Option<i64>,
pub fields: HashMap<String, serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub keyword_fields: Option<HashMap<String, bool>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata_fields: Option<HashMap<String, i32>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InsertRecordRequest {
pub collection: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub expiry: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
pub record: HashMap<String, serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata_fields: Option<HashMap<String, AttrType>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub embedding_provider: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fields: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub keyword_fields: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vectors: Option<HashMap<String, Vec<f32>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InsertRecordResponse {
pub success: bool,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub record: Option<RecordData>,
#[serde(skip_serializing_if = "Option::is_none")]
pub remaining_records: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum IngestSourceType {
File,
#[serde(rename = "mongodb")]
MongoDB,
}
impl IngestSourceType {
pub fn is_valid(&self) -> bool {
matches!(self, IngestSourceType::File | IngestSourceType::MongoDB)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IngestRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub file_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_type: Option<IngestSourceType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub database_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mongo_collection: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub query: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mongo_fetch_batch_size: Option<i32>,
pub collection_name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub keyword_fields: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata_fields: Option<HashMap<String, AttrType>>,
pub fields: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id_field: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expiry_field: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub embedding_provider: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub embedding_model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ingestion_batch_size: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IngestResponse {
pub success: bool,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub details: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListIngestionSourcesResponse {
pub message: String,
pub success: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Vec<IngestSourceType>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct FileReaderOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<IngestSourceType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mongo_filter: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub skip: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<i32>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
pub enum FilterOp {
Equals = 0,
NotEquals = 1,
GreaterThan = 2,
GreaterThanOrEqual = 3,
LessThan = 4,
LessThanOrEqual = 5,
In = 6,
NotIn = 7,
}
impl FilterOp {
pub fn as_str(&self) -> &'static str {
match self {
FilterOp::Equals => "=",
FilterOp::NotEquals => "!=",
FilterOp::GreaterThan => ">",
FilterOp::GreaterThanOrEqual => ">=",
FilterOp::LessThan => "<",
FilterOp::LessThanOrEqual => "<=",
FilterOp::In => "IN",
FilterOp::NotIn => "NOT IN",
}
}
}
impl<'de> Deserialize<'de> for FilterOp {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = i32::deserialize(deserializer)?;
match value {
0 => Ok(FilterOp::Equals),
1 => Ok(FilterOp::NotEquals),
2 => Ok(FilterOp::GreaterThan),
3 => Ok(FilterOp::GreaterThanOrEqual),
4 => Ok(FilterOp::LessThan),
5 => Ok(FilterOp::LessThanOrEqual),
6 => Ok(FilterOp::In),
7 => Ok(FilterOp::NotIn),
_ => Err(serde::de::Error::custom(format!(
"Invalid attribute type: {}",
value
))),
}
}
}
impl Serialize for FilterOp {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_i32(*self as i32)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FilterExpression {
#[serde(skip_serializing_if = "Option::is_none")]
pub attribute: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub op: Option<FilterOp>,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub values: Option<Vec<serde_json::Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct CompoundFilter {
#[serde(skip_serializing_if = "Option::is_none")]
pub and: Option<Vec<FilterExpression>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
pub enum SortOrder {
Ascending = 0,
Descending = 1,
}
impl SortOrder {
pub fn as_str(&self) -> &'static str {
match self {
SortOrder::Ascending => "ASC",
SortOrder::Descending => "DESC",
}
}
}
impl<'de> Deserialize<'de> for SortOrder {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = i32::deserialize(deserializer)?;
match value {
0 => Ok(SortOrder::Ascending),
1 => Ok(SortOrder::Descending),
_ => Err(serde::de::Error::custom(format!(
"Invalid sort order: {}",
value
))),
}
}
}
impl Serialize for SortOrder {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_i32(*self as i32)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SortExpression {
pub attribute: String,
pub order: SortOrder,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct CompoundSort {
#[serde(skip_serializing_if = "Option::is_none")]
pub sorts: Option<Vec<SortExpression>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchRequest {
pub collection: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub query: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fields: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub weights: Option<HashMap<String, f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_distance: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub filters: Option<CompoundFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sort: Option<CompoundSort>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vector_query: Option<Vec<f32>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchResponse {
pub success: bool,
pub message: Option<String>,
pub data: Vec<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StorageItem {
pub name: String,
#[serde(rename = "isDir")]
pub is_dir: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StorageData {
pub items: Vec<StorageItem>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListStorageResponse {
pub success: bool,
pub message: String,
pub data: StorageData,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReadDocumentResponse {
pub success: bool,
pub message: String,
pub data: Vec<HashMap<String, String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthResponse {
pub success: bool,
pub version: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugDistanceData {
pub distance: f64,
pub vector: Vec<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugDistanceResponse {
pub success: bool,
pub message: String,
pub data: DebugDistanceData,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugNeighbor {
pub node_id: i32,
pub vector_id: String,
pub field: String,
pub distance: f64,
pub metadata: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugNodeInfo {
pub node_id: i32,
pub vector_id: String,
pub field: String,
pub level: i32,
pub metadata: HashMap<String, serde_json::Value>,
pub neighbors: Vec<DebugNeighbor>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugNodeInfoResponse {
pub success: bool,
pub message: String,
pub data: Option<DebugNodeInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugLevelInfo {
pub level: i32,
pub node_count: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugLevelsResponse {
pub success: bool,
pub message: String,
pub data: HashMap<String, Vec<DebugLevelInfo>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugNodesAtLevelResponse {
pub success: bool,
pub message: String,
pub data: HashMap<String, Vec<i32>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugVectorNode {
pub id: i32,
pub field: String,
pub vector: Vec<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugReferenceNode {
pub id: String,
pub metadata: HashMap<String, serde_json::Value>,
pub nodes: Vec<DebugVectorNode>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DebugReferenceNodeResponse {
pub success: bool,
pub message: String,
pub data: Option<DebugReferenceNode>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EmbeddingModel {
pub name: String,
pub is_default: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EmbeddingProvider {
pub name: String,
pub is_default: bool,
pub models: Vec<EmbeddingModel>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListEmbeddingModelsResponse {
pub success: bool,
pub message: String,
pub data: Vec<EmbeddingProvider>,
pub supports_distributed_embedding: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum OpType {
Insert,
Update,
Delete,
#[serde(rename = "drop_collection")]
DropCollection,
#[serde(rename = "rename_collection")]
RenameCollection,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Record {
pub id: String,
pub fields: HashMap<String, serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub keyword_fields: Option<HashMap<String, bool>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata_fields: Option<HashMap<String, AttrType>>,
#[serde(skip)]
pub vectors: Option<HashMap<String, Vec<f32>>>,
#[serde(skip)]
pub dist: Option<f32>,
#[serde(skip)]
pub nodes: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expiry: Option<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OplogEntry {
pub lsn: u64,
pub timestamp: String,
pub collection: String,
pub doc_id: String,
pub op_type: OpType,
#[serde(skip_serializing_if = "Option::is_none")]
pub vector: Option<Vec<f32>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub keywords: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub full_doc: Option<Record>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vectors: Option<HashMap<String, Vec<f32>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fields: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub keyword_fields: Option<HashMap<String, bool>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata_fields: Option<HashMap<String, AttrType>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expiry: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub new_name: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OplogStatusResponse {
pub success: bool,
pub message: String,
pub last_lsn: u64,
pub retention_lsn: u64,
pub replica_count: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateReplicaLSNRequest {
pub collection: String,
pub replica_id: String,
pub lsn: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateReplicaLSNResponse {
pub success: bool,
pub message: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RegisterReplicaRequest {
pub replica_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UnRegisterReplicaRequest {
pub replica_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetOplogResponse {
pub success: bool,
pub message: String,
pub entries: Vec<OplogEntry>,
pub last_lsn: u64,
pub count: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Replica {
pub id: String,
pub address: String,
pub is_healthy: bool,
pub is_syncing: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Status {
pub write_replica: Replica,
pub read_replicas: Vec<Replica>,
pub available_count: i32,
pub total_count: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProxyStats {
pub active_proxies: i32,
pub targets: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiscoveryStats {
pub registry: Status,
pub proxy: ProxyStats,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum SyncStatus {
Ready,
Syncing,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateSyncStatusRequest {
pub account_id: String,
pub address: String,
pub status: SyncStatus,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RegisterToDiscoveryRequest {
pub account_id: String,
pub address: String,
pub id: String,
pub is_read: bool,
pub is_write: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReplicaType {
Read,
Write,
SingleNode,
}
impl ReplicaType {
pub fn is_read(&self) -> bool {
matches!(self, ReplicaType::Read)
}
pub fn is_write(&self) -> bool {
matches!(self, ReplicaType::Write)
}
pub fn is_single_node(&self) -> bool {
matches!(self, ReplicaType::SingleNode)
}
}