Calling async function inside of async function results in lifetime issues

102 views Asked by At

The function run_av_check receives a vector filled with URLs which need to get called using reqwest. Iterating through the URLs gives me the error that the borrowed value does not live long enough. My understanding is that as long as check_availability is not finished for all URLs which are called in run_av_check using a for loop the run_av_check function is not finished, therefore the variable URLs should still exist during the runtime of all check_availibility calls.

I have read the Tokio and Rust documentation but I am not able to find a clue how and why this behaviour occurs. Why does the error pop up and what needs to be changed to make this work, both program wise and in my way of thinking?

async fn check_availability(host: &str) -> Result<reqwest::StatusCode, reqwest::Error> {
    // ... building url
    match client.get(&url).send().await {
        Ok(r) => Ok(r.status()),
        Err(_e) => Ok(reqwest::StatusCode::GATEWAY_TIMEOUT),
    }
}

async fn run_av_check(urls: Vec<std::string::String>) -> Result<AvResponse, AvError> {
    let mut av_urls: Vec<std::string::String> = vec![];
    let mut s: std::string::String = "".to_string();
    let mut attributes = Vec::new();

    for url in urls.iter() {
        attributes.push(("instance", url));
        let resp = tokio::task::spawn(check_availability(url));
        // ... processing result
        let res = AvResponse {
            av_urls,
            prom_details: s,
        };
        Ok(res)
    }
}
1

There are 1 answers

0
Angelicos Phosphoros On

The problem is that you are starting independent tasks in tokio::task::spawn(check_availability(url));

This function takes only 'static references but your url refers to the local vector urls.

You need to make check_availability accept the String type (fn check_availability(host: String)) and call it like let resp = tokio::task::spawn(check_availability(url.to_string()));