manticoresoftware / manticoresoftware/manticoresearch-rust

Do not use unwrap and reduce serialization times

Open
#2 11 comments 0 reactions 1 assignee View on GitHub

@Nick-S-2018 is already working on this.

Since Jul 17, 2025.

bug waiting
Dominant language
Rust
Stars
15
Forks
1
PR merge metrics
No merged PRs in 30d

Description

Bug Description:
  1. serde serialize should not unwrap:
    https://github.com/manticoresoftware/manticoresearch-rust/blob/121a76d4379524e3dd211425392f7a5aea2c79e4/src/apis/request.rs#L73
  2. Would it be better to use generics for the doc field of InsertDocumentRequest to avoid serializing twice?https://github.com/manticoresoftware/manticoresearch-rust/blob/121a76d4379524e3dd211425392f7a5aea2c79e4/src/models/insert_document_request.rs#L28

Maybe the following code will work

InsertDocumentRequest with generic:
use crate::models;
use serde::{Deserialize, Serialize};

/// InsertDocumentRequest : Object containing data for inserting a new document into the table
#[derive(Clone, Debug, Serialize)]
pub struct InsertDocumentRequest<'a, T> {
    /// Name of the table to insert the document into
    pub table: &'a str,
    /// Name of the cluster to insert the document into
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cluster: Option<&'a str>,
    /// Document ID. If not provided, an ID will be auto-generated
    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<i64>,
    /// Object containing document data
    pub doc: &'a T,
}

impl<'a, T> InsertDocumentRequest<'a, T> {
    /// Object containing data for inserting a new document into the table
    pub fn new(table: &'a str, doc: &'a T) -> InsertDocumentRequest<'a, T> {
        InsertDocumentRequest {
            table,
            cluster: None,
            id: None,
            doc,
        }
    }
}
IndexApiClient use generic without trait:
/*
 * Manticore Search Client
 *
 * Сlient for Manticore Search.
 *
 * The version of the OpenAPI document: 5.0.0
 * Contact: info@manticoresearch.com
 * Generated by: https://openapi-generator.tech
*/

use std::borrow::Borrow;
#[allow(unused_imports)]
use std::option::Option;
use std::pin::Pin;
use std::sync::Arc;

use futures::Future;
use hyper::{self, Method};
use hyper_util::client::legacy::connect::Connect;
use serde::Serialize;

use super::request::Request;
use super::{configuration, Error};
use crate::models::{
    BulkResponse, DeleteDocumentRequest, DeleteResponse, InsertDocumentRequest,
    ReplaceDocumentRequest, SuccessResponse, UpdateResponse,
};

pub struct IndexApiClient<C: Connect>
where
    C: Clone + std::marker::Send + Sync + 'static,
{
    configuration: Arc<configuration::Configuration<C>>,
}

impl<C: Connect> IndexApiClient<C>
where
    C: Clone + std::marker::Send + Sync,
{
    pub fn new(configuration: Arc<configuration::Configuration<C>>) -> IndexApiClient<C> {
        IndexApiClient { configuration }
    }
}

impl<C: Connect> IndexApiClient<C>
where
    C: Clone + std::marker::Send + Sync,
{
    #[allow(unused_mut)]
    pub async fn bulk<'a, T>(
        &self,
        docs: &[InsertDocumentRequest<'a, T>],
    ) -> Result<BulkResponse, Error>
    where
        T: Serialize,
    {
        let mut buffer = Vec::new();
        for x in docs.iter() {
            if !buffer.is_empty() {
                buffer.push(b'\n');
            }

            serde_json::to_writer(&mut buffer, x)?;
        }

        let body = String::from_utf8(buffer).unwrap_or_default();

        Request::new(Method::POST, "/bulk")
            .with_body_string(body)
            .execute(&self.configuration)
            .await
    }

    pub async fn bulk_str<T: Into<String>>(&self, doc: T) -> Result<BulkResponse, Error> {
        Request::new(Method::POST, "/bulk")
            .with_body_string(doc.into())
            .execute(&self.configuration)
            .await
    }

    #[allow(unused_mut)]
    pub async fn delete(
        &self,
        delete_document_request: &DeleteDocumentRequest,
    ) -> Result<DeleteResponse, Error> {
        Request::new(Method::POST, "/delete")
            .with_body_param(delete_document_request)?
            .execute(&self.configuration)
            .await
    }

    #[allow(unused_mut)]
    pub async fn insert<'a, T: Serialize>(
        &self,
        insert_document_request: &InsertDocumentRequest<'a, T>,
    ) -> Result<SuccessResponse, Error> {
        Request::new(Method::POST, "/insert")
            .with_body_param(insert_document_request)?
            .execute(&self.configuration)
            .await
    }

    #[allow(unused_mut)]
    pub async fn partial_replace(
        &self,
        table: &str,
        id: i64,
        replace_document_request: &ReplaceDocumentRequest,
    ) -> Result<UpdateResponse, Error> {
        Request::new(Method::POST, "/{table}/_update/{id}")
            .with_path_param("table".to_string(), table.to_string())
            .with_path_param("id".to_string(), id.to_string())
            .with_body_param(replace_document_request)?
            .execute(&self.configuration)
            .await
    }

    #[allow(unused_mut)]
    pub async fn replace<'a, T: Serialize>(
        &self,
        insert_document_request: &InsertDocumentRequest<'a, T>,
    ) -> Result<SuccessResponse, Error> {
        Request::new(Method::POST, "/replace")
            .with_body_param(insert_document_request)?
            .execute(&self.configuration)
            .await
    }

    #[allow(unused_mut)]
    pub async fn update(
        &self,
        update_document_request: &DeleteDocumentRequest,
    ) -> Result<UpdateResponse, Error> {
        Request::new(Method::POST, "/update")
            .with_body_param(update_document_request)?
            .execute(&self.configuration)
            .await
    }
}


SearchApiClient with trait
/*
 * Manticore Search Client
 *
 * Сlient for Manticore Search.
 *
 * The version of the OpenAPI document: 5.0.0
 * Contact: info@manticoresearch.com
 * Generated by: https://openapi-generator.tech
 */

use std::borrow::Borrow;
#[allow(unused_imports)]
use std::option::Option;
use std::pin::Pin;
use std::sync::Arc;

use futures::Future;
use hyper;
use hyper_util::client::legacy::connect::Connect;

use super::request as __internal_request;
use super::{configuration, Error};
use crate::models;

pub struct SearchApiClient<C: Connect>
where
    C: Clone + std::marker::Send + Sync + 'static,
{
    configuration: Arc<configuration::Configuration<C>>,
}

impl<C: Connect> SearchApiClient<C>
where
    C: Clone + std::marker::Send + Sync,
{
    pub fn new(configuration: Arc<configuration::Configuration<C>>) -> SearchApiClient<C> {
        SearchApiClient { configuration }
    }
}

pub trait SearchApi: Send + Sync {
    fn autocomplete(
        &self,
        autocomplete_request: &models::AutocompleteRequest,
    ) -> Result<Pin<Box<dyn Future<Output = Result<Vec<serde_json::Value>, Error>> + Send>>, Error>;
    fn percolate(
        &self,
        table: &str,
        percolate_request: &models::PercolateRequest,
    ) -> Result<
        Pin<Box<dyn Future<Output = Result<crate::models::SearchResponse, Error>> + Send>>,
        Error,
    >;
    fn search(
        &self,
        search_request: &models::SearchRequest,
    ) -> Result<
        Pin<Box<dyn Future<Output = Result<crate::models::SearchResponse, Error>> + Send>>,
        Error,
    >;
}

impl<C: Connect> SearchApi for SearchApiClient<C>
where
    C: Clone + std::marker::Send + Sync,
{
    #[allow(unused_mut)]
    fn autocomplete(
        &self,
        autocomplete_request: &models::AutocompleteRequest,
    ) -> Result<Pin<Box<dyn Future<Output = Result<Vec<serde_json::Value>, Error>> + Send>>, Error>
    {
        let mut req =
            __internal_request::Request::new(hyper::Method::POST, "/autocomplete".to_string());
        req = req.with_body_param(autocomplete_request)?;

        Ok(req.execute(&self.configuration))
    }

    #[allow(unused_mut)]
    fn percolate(
        &self,
        table: &str,
        percolate_request: &models::PercolateRequest,
    ) -> Result<
        Pin<Box<dyn Future<Output = Result<crate::models::SearchResponse, Error>> + Send>>,
        Error,
    > {
        let mut req =
            __internal_request::Request::new(hyper::Method::POST, "/pq/{table}/search".to_string());

        req.with_path_param("table".to_string(), table.to_string())
            .with_body_param(percolate_request)
            .map(|x| x.execute(&self.configuration))
    }

    #[allow(unused_mut)]
    fn search(
        &self,
        search_request: &models::SearchRequest,
    ) -> Result<
        Pin<Box<dyn Future<Output = Result<crate::models::SearchResponse, Error>> + Send>>,
        Error,
    > {
        let mut req = __internal_request::Request::new(hyper::Method::POST, "/search".to_string());
        req.with_body_param(search_request)
            .map(|x| x.execute(&self.configuration))
    }
}
Manticore Search Version:

x

Client Version:

1

Have you tried the latest development version of Manticore Search and the client?

Yes

Internal Checklist:

To be completed by the assignee. Check off tasks that have been completed or are not applicable.

  • Implementation completed
  • Tests developed
  • Documentation updated
  • Documentation reviewed

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.