Make the loop await till async fn finished its work and run it again

Hi everyone, I'll be as short as possible. Any help would be appreciated.
I have an 'async fn timer_updatable' which collects the data and parses the site every 60 seconds. And sometimes (maybe 2 times per month) it panics because it can't collect the final structure (I think it happens because it parses the site from html and sometimes it can't match all the elements).
I decided to launch an infinite loop, so if timer_updatable fails or panics because of some Err this loop relaunches it again. And I can't figure out how to acomplish this task. Every time I try it launches lots of 'fn timer_updatable'

pub async fn retriable_timer(updatable_link : Arc<Mutex<Vec<GroupEvent>>>) -> () {
    spawn_blocking(move || {
        loop {
            println!("Looper is spawned");
            let cloned = Arc::clone(&updatable_link);
            timer_updatable(cloned); // Async fn which collects the data and parses the site
        }
    });
}

Infinite async fn timer_updatable which reloads the data.

pub async fn timer_updatable(updatable_link : Arc<Mutex<Vec<GroupEvent>>>) -> () {
    tokio::spawn(async move {
        let mut timer : u8 = 60;
        loop {
            if timer == 0 {
                let mut processed : Vec<JoinHandle<()>> = Vec::new();
                println!("Started loading the data at {}\n", Local::now().format("[%Y-%m-%d][%H:%M:%S]"));
                let mut answer = ParseManage::na_collected().await; // Get main page with a check for connection. Retry till it's fine.
                let copied = answer.clone();
                let to_fill : Arc<Mutex<Vec<DataStructs::MapsToMatch>>> = Arc::new(Mutex::new(Vec::new()));
                for links in copied {
                    let fill_copy = Arc::clone(&to_fill);
                    let spawned_thread = tokio::spawn(async move {
                        println!("Spawned a thread for : {}", links.link);
                        let retrieved = ParseManage::retrieve_maps(links.link).await;
                        let mut unlocked = fill_copy.lock().await;
                        println!("{:#?}", retrieved);
                        unlocked.push(retrieved);
                    });
                    processed.push(spawned_thread)

                }
                futures::future::join_all(processed).await;
                for elements in to_fill.lock().await.iter() {
                    for control in answer.iter_mut() {
                        if elements.link.to_string() == control.link.to_string() {
                            control.yandex_maps = elements.map.to_string();
                            control.subway_colored = elements.subway.clone();
                        }
                    }
                }
                let mut opened_value = updatable_link.lock().await;
                *opened_value = answer;
                println!("{:#?}", *opened_value);
                drop(opened_value);
                timer = 60
            }
            else {
                sleep(Duration::from_secs(1)).await;
                timer -= 1;
            }
        }
    });
}

Both of these functions are marked async but they don't .await anything (they just spawn tasks and then immediately return). Perhaps you wanted timer_updatable to be an async function with the body of code (in which case, delete the call to spawn)?

Also, spawn_blocking is not meant for infinite loops, as the thread pool is optimized for a bunch of short tasks. You probably don't want the spawn_blocking either and for the loop to be the body of the async function.

Thanks for your explanation, I removed 'async' in theese annotations. Feels like I was a robot when I wrote it

Finaly solved this case, I've just spawned another async thread with tokio. And if it crashes timer is still active so it can relaunch the update in 60 seconds.
It differs from my question in the header, but this solving is pretty good for me. I hope it would help sb in the future

pub async fn timer_updatable(updatable_link : Arc<Mutex<Vec<GroupEvent>>>) -> () {
    tokio::spawn(async move {
        let mut timer : u8 = 60;
        loop {
            if timer == 0 {
                let cloned_updatable = Arc::clone(&updatable_link);
                tokio::spawn(async move { // Here I've added a new async thread.
                    let mut processed : Vec<JoinHandle<()>> = Vec::new();
                    println!("Started loading the data at {}\n", Local::now().format("[%Y-%m-%d][%H:%M:%S]"));
                    let mut answer = ParseManage::na_collected().await; // Get main page with a check for connection. Retry till it's fine.
                    let copied = answer.clone();
                    let to_fill : Arc<Mutex<Vec<DataStructs::MapsToMatch>>> = Arc::new(Mutex::new(Vec::new()));
                    for links in copied {
                    let fill_copy = Arc::clone(&to_fill);
                    let spawned_thread = tokio::spawn(async move {
                        println!("Spawned a thread for : {}", links.link);
                        let retrieved = ParseManage::retrieve_maps(links.link).await;
                        let mut unlocked = fill_copy.lock().await;
                        println!("{:#?}", retrieved);
                        unlocked.push(retrieved);
                    });
                    processed.push(spawned_thread)
                    }
                    futures::future::join_all(processed).await;
                    for elements in to_fill.lock().await.iter() {
                    for control in answer.iter_mut() {
                        if elements.link.to_string() == control.link.to_string() {
                            control.yandex_maps = elements.map.to_string();
                            control.subway_colored = elements.subway.clone();
                        }
                    }
                }
                    let mut opened_value = cloned_updatable.lock().await;
                    *opened_value = answer;
                    println!("{:#?}", *opened_value);
                    drop(opened_value);
                });
                timer = 60;
            }
            else {
                println!("Time estimated till base is updated : {}", timer);
                sleep(Duration::from_secs(1)).await;
                timer -= 1;
            }
        }
    });
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.