1

I have the following error in my Rust API.

error: future cannot be sent between threads safely
   --> src/bin/server/server.rs:115:5
    |
115 | /     {
116 | |         info!("identity_create_post({:?}) - X-Span-ID: {:?}", id_create_request, context.get().0.clone());
117 | |         let did: String = match id::create_identity(format!("./{}.hodl", id_create_request.user_id.unwrap()).as_str(), id_create_request.stronghold_password.unwrap().as_str()).await {
118 | |             Ok(did) => did,
...   |
121 | |         Ok(IdentityCreatePostResponse::TheIdentityHasBeenCreatedSuccessfully(models::IdCreateResponse{did:Some(did)}))
122 | |     }
    | |_____^ future created by async block is not `Send`
    |
    = help: the trait `std::marker::Send` is not implemented for `dyn futures::Future<Output = Result<std::string::String, JwkStorageDocumentError>>`
note: future is not `Send` as it awaits another future which is not `Send`
   --> src/bin/server/id.rs:49:26
    |
49  |       let fragment = match document
    |  __________________________^
50  | |     .generate_method(
51  | |       &storage,
52  | |       KeyType::from_static_str("Ed25519"),
...   |
55  | |       MethodScope::VerificationMethod,
56  | |     ).await {
    | |_____^ await occurs here on type `Pin<Box<dyn futures::Future<Output = Result<std::string::String, JwkStorageDocumentError>>>>`, which is not `Send`
    = note: required for the cast from `Pin<Box<{async block@src/bin/server/server.rs:115:5: 122:6}>>` to `Pin<Box<dyn futures::Future<Output = Result<IdentityCreatePostResponse, ApiError>> + std::marker::Send>>

I think the error es fairly common, but I couldn't extract the solution in the threads I have seen so far. I have a function in my API where I call an inner function.

#[async_trait]
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString> + Send + Sync
{
    /// Create a new identity on the ledger
    async fn identity_create_post(
        &self,
        id_create_request: models::IdCreateRequest,
        context: &C) -> Result<IdentityCreatePostResponse, ApiError>
    {
        info!("identity_create_post({:?}) - X-Span-ID: {:?}", id_create_request, context.get().0.clone());
        let identifier: String = match id::create_identity(format!("./{}.keys", id_create_request.user_id.unwrap()).as_str(), id_create_request.stronghold_password.unwrap().as_str()).await {
            Ok(identifier) => identifier,
            Err(e) => {return Err(ApiError(format!("Error creating the identity: {:?}",e).to_string()))},
        };
        Ok(IdentityCreatePostResponse::TheIdentityHasBeenCreatedSuccessfully(models::IdCreateResponse{did:Some(did)}))
    }
...

The error occurrs in the line with the await as inside the function call there is an await with a future without Send.

The part that causes the error is the following.

let fragment = match document
    .generate_method(
      &storage,
      KeyType::from_static_str("Ed25519"),
      JwsAlgorithm::EdDSA,
      None,
      MethodScope::VerificationMethod,
    ).await {
      Ok(fragment) => fragment,
      Err(_) => panic!(),
    };
println!("-----------------------------\n{:?}",document);
drop(fragment);

The function generate_method is not mine and cannot be changed. How can I change the code shown before to solve the error? I have read that it involves Boxing the result, but I have no clue how to do it.

0

1 Answer 1

0

Probably it's not the best way to solve it but I came up with a solution to this. I hope it helps if someone has a similar problem.

let mut document = Arc::new(Mutex::new(IotaDocument::new(&network_name)));
let mut document_clone = Arc::clone(&document);
let result = tokio::task::spawn_blocking(move || {
  let mut document_clone = document_clone.lock().unwrap();
  futures::executor::block_on(document_clone.generate_method(
      &storage,
      KeyType::from_static_str("Ed25519"),
      JwsAlgorithm::EdDSA,
      None,
      MethodScope::VerificationMethod,
  ))
}).await??;
let document_clone = document.lock().unwrap().clone();
drop(document);
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.