rustrust-tokiotauri

Future cannot be sent between threads safely when trying to await a vec of futures


I'm using Tauri and trying to download parts in batches. I run the functions on a batch and wait for them to finish.

I get this error:

future cannot be sent between threads safely
within `impl futures::Future<Output = Result<Vec<std::string::String>,
std::string::String>>`, the trait `std::marker::Send` is not implemented for `Rc<Node>`, 
which is required by `impl futures::Future<Output = Result<Vec<std::string::String>, 
std::string::String>>: std::marker::Send`

I have marked below where the error shows up and which line seems to cause it.

#[tauri::command] // ERROR here
async fn handle_download_file(source: &str, url: &str, batch_size: usize,) -> Result<Vec<String>, String> {
    source::download_file(source, url, batch_size).await
}

pub async fn download_file(url: &str, batch_size: usize) -> Result<Vec<String>, String> {
    let document = kuchikiki::parse_html().one("<html></html>");

    // ERROR because of this line
    let total_pages = get_total_pages(&document).await;

    Ok(vec![])
}

async fn get_total_pages(document: &NodeRef) -> usize {
    let mut total_pages = 1;

    let last_page_node = match document.select("#list-chapter ul.pagination > li.last a") {
        Ok(mut nodes) => nodes.next(),
        Err(_) => None,
    };

    match last_page_node {
        Some(node) => {
            let last_page_url = node.attributes.borrow().get("href").unwrap().to_string();
            let total_page = last_page_url
                .split("=")
                .last()
                .expect("Couldn't get last split at '='")
                .parse::<usize>()
                .unwrap_or(1);
            total_pages = total_page;
        }
        None => {
            total_pages = 1;
        }
    };

    return total_pages;
}

For a working example: The error happens here because of this line


Solution

  • As answered on the Rust-Lang Forum:

    kuchikiki::NodeRef can't be shared between threads because it is !Send as it stores an Rc (not threadsafe reference counted pointer type) internally. To fix this problem, avoid keeping a NodeRef across .await points.