linkrs-sync 0.1.0

Synchronization primitives for Linkrs
Documentation
use thiserror::Error;

use crate::SyncError;
use linkrs_fulltext::error::SearchError;

#[derive(Error, Debug, Clone)]
pub enum FulltextError {
    #[error("Index not found: {0}")]
    IndexNotFound(String),

    #[error("Index already exists: {0}")]
    IndexAlreadyExists(String),

    #[error("Engine not found for space {space_id}, tag {tag_name}, field {field_name}")]
    EngineNotFound {
        space_id: u64,
        tag_name: String,
        field_name: String,
    },

    #[error("Engine unavailable: {0}")]
    EngineUnavailable(String),

    #[error("Index corrupted: {0}")]
    IndexCorrupted(String),

    #[error("Query parse error: {0}")]
    QueryParseError(String),

    #[error("Invalid document ID: {0}")]
    InvalidDocId(String),

    #[error("Index configuration error: {0}")]
    ConfigError(String),

    #[error("Index operation timeout")]
    Timeout,

    #[error("Index is locked: {0}")]
    Locked(String),

    #[error("Index operation cancelled")]
    Cancelled,

    #[error("Internal error: {0}")]
    Internal(String),
}

#[derive(Error, Debug, Clone)]
pub enum CoordinatorError {
    #[error("Fulltext index error: {0}")]
    Fulltext(#[from] FulltextError),

    #[error("Sync error: {0}")]
    Sync(String),

    #[error("Index creation failed for {tag_name}.{field_name}: {reason}")]
    IndexCreationFailed {
        tag_name: String,
        field_name: String,
        reason: String,
    },

    #[error("Index drop failed for {tag_name}.{field_name}: {reason}")]
    IndexDropFailed {
        tag_name: String,
        field_name: String,
        reason: String,
    },

    #[error("Index rebuild failed: {0}")]
    IndexRebuildFailed(String),

    #[error("Vertex change processing failed: {0}")]
    VertexChangeFailed(String),

    #[error("Space not found: {0}")]
    SpaceNotFound(u64),

    #[error("Tag not found: {0}")]
    TagNotFound(String),

    #[error("Field not indexed: {tag_name}.{field_name}")]
    FieldNotIndexed {
        tag_name: String,
        field_name: String,
    },

    #[error("Coordinator not initialized")]
    NotInitialized,

    #[error("Coordinator is shutting down")]
    ShuttingDown,

    #[error("Invalid operation: {0}")]
    InvalidOperation(String),

    #[error("Internal error: {0}")]
    Internal(String),
}

pub type FulltextResult<T> = std::result::Result<T, FulltextError>;
pub type CoordinatorResult<T> = std::result::Result<T, CoordinatorError>;

impl From<SearchError> for FulltextError {
    fn from(err: SearchError) -> Self {
        match err {
            SearchError::EngineNotFound(msg) => FulltextError::EngineNotFound {
                space_id: 0,
                tag_name: String::new(),
                field_name: msg,
            },
            SearchError::IndexNotFound(msg) => FulltextError::IndexNotFound(msg),
            SearchError::IndexAlreadyExists(msg) => FulltextError::IndexAlreadyExists(msg),
            SearchError::SpaceNotFound(space_id) => {
                FulltextError::Internal(format!("Space not found: {}", space_id))
            }
            SearchError::TagNotFound(tag) => {
                FulltextError::Internal(format!("Tag not found: {}", tag))
            }
            SearchError::FieldNotFound(field) => {
                FulltextError::Internal(format!("Field not found: {}", field))
            }
            SearchError::EngineUnavailable => {
                FulltextError::EngineUnavailable("engine unavailable".to_string())
            }
            SearchError::IndexCorrupted(msg) => FulltextError::IndexCorrupted(msg),
            #[cfg(feature = "fulltext")]
            SearchError::TantivyError(e) => FulltextError::Internal(e.to_string()),
            SearchError::IoError(e) => FulltextError::Internal(e.to_string()),
            SearchError::SerializationError(msg) => {
                FulltextError::Internal(format!("Serialization error: {}", msg))
            }
            SearchError::ConfigError(msg) => FulltextError::ConfigError(msg),
            SearchError::QueryParseError(msg) => FulltextError::QueryParseError(msg),
            SearchError::InvalidDocId(msg) => FulltextError::InvalidDocId(msg),
            SearchError::RebuildBusy(msg) => {
                FulltextError::Internal(format!("Rebuild busy: {}", msg))
            }
            SearchError::Internal(msg) => FulltextError::Internal(msg),
        }
    }
}

impl From<SyncError> for CoordinatorError {
    fn from(err: SyncError) -> Self {
        CoordinatorError::Sync(err.to_string())
    }
}

impl From<SearchError> for CoordinatorError {
    fn from(err: SearchError) -> Self {
        CoordinatorError::Fulltext(FulltextError::from(err))
    }
}