Repository: qdrant/qdrant
File: lib/collection/src/operations/types.rs (Rust)

Code before:
    },
    #[error("Remote shard on {peer_id} failed during forward proxy operation: {error}")]
    ForwardProxyError { peer_id: PeerId, error: Box<Self> },
    #[error("Out of memory, free: {free}, {description}")]
    OutOfMemory { description: String, free: u64 },
    #[error("Timeout error: {description}")]
    Timeout { description: String },
    #[error("Precondition failed: {description}")]
    PreConditionFailed { description: String },
    #[error("Object Store error: {what}")]
    ObjectStoreError { what: String },
    #[error("Strict mode error: {description}")]
    StrictMode { description: String },
    #[error("{description}")]
    InferenceError { description: String },
    #[error("Rate limiting exceeded: {description}")]
    RateLimitExceeded {
        description: String,
        retry_after: Option<Duration>,
    },
    #[error("Shard temporarily unavailable: {description}")]
    ShardUnavailable { description: String },
}

impl CollectionError {
    pub fn timeout(timeout_ms: u128, operation: impl Into<String>) -> Self {
        let timeout_str = if timeout_ms < 1000 {
            format!("{timeout_ms} milliseconds")
        } else if timeout_ms % 1000 == 0 {
            format!("{} seconds", timeout_ms / 1000)
        } else {
            format!("{:.3} seconds", timeout_ms as f64 / 1000.0)
        };
        Self::Timeout {
            description: format!(
                "Operation '{}' timed out after {}",
                operation.into(),
                timeout_str
            ),
        }
    }

    pub fn service_error(error: impl Into<String>) -> Self {
        Self::ServiceError {
            error: error.into(),
            backtrace: Some(Backtrace::force_capture().to_string()),
        }
    }

    pub fn bad_input(description: impl Into<String>) -> Self {
        Self::BadInput {

Review comment (bug):
@copilot The timeout function should take the timeout as a `Duration` type.

We can then display it nicely with a debug format instead of reinventing the wheel.

Code after:
    },
    #[error("Remote shard on {peer_id} failed during forward proxy operation: {error}")]
    ForwardProxyError { peer_id: PeerId, error: Box<Self> },
    #[error("Out of memory, free: {free}, {description}")]
    OutOfMemory { description: String, free: u64 },
    #[error("Timeout error: {description}")]
    Timeout { description: String },
    #[error("Precondition failed: {description}")]
    PreConditionFailed { description: String },
    #[error("Object Store error: {what}")]
    ObjectStoreError { what: String },
    #[error("Strict mode error: {description}")]
    StrictMode { description: String },
    #[error("{description}")]
    InferenceError { description: String },
    #[error("Rate limiting exceeded: {description}")]
    RateLimitExceeded {
        description: String,
        retry_after: Option<Duration>,
    },
    #[error("Shard temporarily unavailable: {description}")]
    ShardUnavailable { description: String },
}

impl CollectionError {
    pub fn timeout(timeout: Duration, operation: impl Into<String>) -> Self {
        Self::Timeout {
            description: format!(
                "Operation '{}' timed out after {timeout:?}",
                operation.into(),
            ),
        }
    }

    pub fn service_error(error: impl Into<String>) -> Self {
        Self::ServiceError {
            error: error.into(),
            backtrace: Some(Backtrace::force_capture().to_string()),
        }
    }

    pub fn bad_input(description: impl Into<String>) -> Self {
        Self::BadInput {
            description: description.into(),
        }
    }

    pub fn not_found(what: impl Into<String>) -> Self {
        Self::NotFound { what: what.into() }
    }