es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo esperar a que finalicen las tareas de tokio?

Estoy intentando escribir en un HashMap utilizando el patrón Arc<Mutex<T>> como parte de un ejercicio de raspado de sitios web inspirado en The Rust Cookbook.

Esta primera parte utiliza la ejecución de tokio. No puedo superar el hecho de que las tareas se completen y devuelvan el HashMap ya que simplemente se cuelga.

type Db = Arc<Mutex<HashMap<String, bool>>>;

pub async fn handle<em>async</em>tasks(db: Db) -> BoxResult<HashMap<String, bool>> {
    let links = NodeUrl::new("https://www.inverness-courier.co.uk/")
        .await
        .unwrap();

let arc = db.clone();

let mut handles = Vec::new();

for link in links.links_with_paths {
    let x = arc.clone();
    handles.push(tokio::spawn(async move {
        process(x, link).await;
    }));
}

futures::future::join_all(handles).await;

let readables = arc.lock().await;

for (key, value) in readables.clone().into_iter() {
    println!("Checking db: k, v ==>{} / {}", key, value);
}

let clone_db = readables.clone();

return Ok(clone_db);
}

async fn process(db: Db, url: Url) {
    let mut db = db.lock().await;
    println!("checking {}", url);

if check_link(&url).await.is_ok() {
    db.insert(url.to_string(), true);
} else {
    db.insert(url.to_string(), false);
}
}

async fn check<em>link(url: &Url) -> BoxResult<bool> {
    let res = reqwest::get(url.as_ref()).await?;
    Ok(res.status() != StatusCode::NOT_FOUND)
}

pub struct NodeUrl {
    domain: String,
    pub links<em>with</em>paths: Vec<Url>,
}

#[tokio::main]
async fn main() {
    let db: Db = Arc::new(Mutex::new(HashMap::new()));

    let db = futures::executor::block_on(task::handle_async_tasks(db));
}

Me gustaría devolver el HashMap a main() donde el hilo principal está bloqueado. ¿Cómo puedo esperar a que se completen todos los procesos roscados asíncronos y devolver el HashMap?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para esperar a que finalicen y retornen todos los procesos enhebrados asíncronos y la HashMap, se puede usar futures::future::join_all para esperar a que todos los handles tokio::spawn finalicen y luego retornar la HashMap clonada. Aquí hay una versión actualizada de la función handle_async_tasks:

    pub async fn handle_async_tasks(db: Db) -> BoxResult<><string, bool="">> {
        let links = NodeUrl::new("https://www.inverness-courier.co.uk/")
            .await
            .unwrap();
    
        let arc = db.clone();
    
        let mut handles = Vec::new();
    
        for link in links.links_with_paths {
            let x = arc.clone();
            handles.push(tokio::spawn(async move {
                process(x, link).await;
            }));
        }
    
        futures::future::join_all(handles).await;
    
        let readables = arc.lock().await.clone();
    
        for (key, value) in readables.clone().into_iter() {
            println!("Checking db: k, v ==> {} / {}", key, value);
        }
    
        Ok(readables)
    }
    

    Tenga en cuenta que clonamos el MutexGuard de Arc<><><string, bool="">>> en readables antes de devolverlo, ya que no se puede devolver el propio guard.</string,></string,>

Comments are closed.