meilisearch / meilisearch-rust

Rust wrapper for the Meilisearch API.

Home Page:https://www.meilisearch.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Updated meilisearch_sdk::errors::Error is no longer Send

c1wren opened this issue · comments

Description
I've been testing the changes using reqwest instead of isahc. Something changed in meilisearch_sdk::errors::Error because it is no longer Send.

Expected behavior
Previous code that used to work should work but it doesn't. I was using tokio::spawn to call functions that in turn use the meilisearch sdk in them.

Current behavior
I get the error: dyn Future<Output = Result<TaskInfo, meilisearch_sdk::errors::Error>> cannot be sent between threads safely

I've created a minimal example to reproduce the issue:

fn is_send<T: Send>() -> bool {
    true
}
is_send::<meilisearch_sdk::errors::Error>() <--- this will not compile because it isn't Send

Environment (please complete the following information):

  • Meilisearch version: N/A
  • meilisearch-rust version: commit revision cb32534
commented

Hey @c1wren thanks a lot for trying it out, I believe I fixed your issue in #571

Let me know if anything else is missing before we make a new release.

@irevoire Thank you for that fix, but it turns out something else is still not the same compared to what it used to be and my code still does not compile.

Here's a minimally reproducible program to test against.

use anyhow::Result;
use meilisearch_sdk::{client::Client, indexes::Index};
use serde::Serialize;

#[tokio::main]
async fn main() -> Result<()> {

    tokio::spawn(post_documents());

    Ok(())
}

#[derive(Serialize)]
struct Doc {
    pub id: i32,
    pub data: String,
}

async fn post_documents() {
    let (_, index) = get_meilisearch_client_and_index().unwrap();
    let docs = Vec::<Doc>::new();

    let _task = index
        .add_documents_in_batches(&docs, Some(5000), Some("id"))
        .await;
}

fn get_meilisearch_client_and_index() -> Result<(Client, Index)> {
    let meilisearch_url = "...";
    let meilisearch_master_key = "...";

    let client = Client::new(meilisearch_url, Some(meilisearch_master_key)).unwrap();

    let index = client.index("docs");

    Ok((client, index))
}

And here's the error:

error[E0277]: `dyn Future<Output = Result<TaskInfo, meilisearch_sdk::errors::Error>>` cannot be sent between threads safely
    --> src/main.rs:17:18
     |
17   |     tokio::spawn(post_documents());
     |     ------------ ^^^^^^^^^^^^^^^^ `dyn Future<Output = Result<TaskInfo, meilisearch_sdk::errors::Error>>` cannot be sent between threads safely
     |     |
     |     required by a bound introduced by this call
     |
     = help: the trait `Send` is not implemented for `dyn Future<Output = Result<TaskInfo, meilisearch_sdk::errors::Error>>`, which is required by `impl Future<Output = ()>: Send`
     = note: required for `Unique<dyn Future<Output = Result<TaskInfo, meilisearch_sdk::errors::Error>>>` to implement `Send`
note: required because it appears within the type `Box<dyn Future<Output = Result<TaskInfo, meilisearch_sdk::errors::Error>>>`
    --> /Users/calebwren/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:195:12
     |
195  | pub struct Box<
     |            ^^^
note: required because it appears within the type `Pin<Box<dyn Future<Output = Result<TaskInfo, meilisearch_sdk::errors::Error>>>>`
    --> /Users/calebwren/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/pin.rs:1090:12
     |
1090 | pub struct Pin<Ptr> {
     |            ^^^
     = note: required because it captures the following types: `std::string::String`, `Pin<Box<dyn Future<Output = Result<TaskInfo, meilisearch_sdk::errors::Error>>>>`
note: required because it's used within this `async` fn body
    --> /Users/calebwren/.cargo/git/checkouts/meilisearch-rust-2524a391b4e4033d/85ceec4/src/indexes.rs:573:34
     |
573  |       ) -> Result<TaskInfo, Error> {
     |  __________________________________^
574  | |         let url = if let Some(primary_key) = primary_key {
575  | |             format!(
576  | |                 "{}/indexes/{}/documents?primaryKey={}",
...    |
592  | |             .await
593  | |     }
     | |_____^
     = note: required because it captures the following types: `impl Future<Output = Result<TaskInfo, meilisearch_sdk::errors::Error>>`
note: required because it's used within this `async` fn body
    --> /Users/calebwren/.cargo/git/checkouts/meilisearch-rust-2524a391b4e4033d/85ceec4/src/indexes.rs:667:34
     |
667  |       ) -> Result<TaskInfo, Error> {
     |  __________________________________^
668  | |         self.add_or_replace(documents, primary_key).await
669  | |     }
     | |_____^
     = note: required because it captures the following types: `&meilisearch_sdk::indexes::Index`, `std::option::Option<&str>`, `Vec<TaskInfo>`, `Chunks<'_, Doc>`, `&mut Vec<TaskInfo>`, `impl Future<Output = Result<TaskInfo, meilisearch_sdk::errors::Error>>`
note: required because it's used within this `async` fn body
    --> /Users/calebwren/.cargo/git/checkouts/meilisearch-rust-2524a391b4e4033d/85ceec4/src/indexes.rs:1530:39
     |
1530 |       ) -> Result<Vec<TaskInfo>, Error> {
     |  _______________________________________^
1531 | |         let mut task = Vec::with_capacity(documents.len());
1532 | |         for document_batch in documents.chunks(batch_size.unwrap_or(1000)) {
1533 | |             task.push(self.add_documents(document_batch, primary_key).await?);
1534 | |         }
1535 | |         Ok(task)
1536 | |     }
     | |_____^
     = note: required because it captures the following types: `meilisearch_sdk::indexes::Index`, `Vec<Doc>`, `impl Future<Output = Result<Vec<TaskInfo>, meilisearch_sdk::errors::Error>>`
note: required because it's used within this `async` fn body
    --> src/main.rs:28:27
     |
28   |   async fn post_documents() {
     |  ___________________________^
29   | |     let (_, index) = get_meilisearch_client_and_index().unwrap();
30   | |     let docs = Vec::<Doc>::new();
31   | |
...    |
34   | |         .await;
35   | | }
     | |_^
note: required by a bound in `tokio::spawn`
    --> /Users/calebwren/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.37.0/src/task/spawn.rs:166:21
     |
164  |     pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
     |            ----- required by a bound in this function
165  |     where
166  |         F: Future + Send + 'static,
     |                     ^^^^ required by this bound in `spawn`
commented

Thanks! I’ll try to look at it this week!