Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Sharing reqwest::Client between tokio tasks

I am trying to spawn several tokio tasks that are supposed to be querying various web APIs. My plan was to use reqwest::Client for that.

According to reqwest::Client docs

The Client holds a connection pool internally, so it is advised that you create one and reuse it.
You do not have to wrap the Client in an Rc or Arc to reuse it, because it already uses an Arc internally.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Trying to just grab the reference results in the usual, expected complaint about 'static

21 |     let webapi1 = tokio::spawn(async {do_stuff(&webapi_client).await});
   |                                      ^^^^^^^^^^^-------------^^^^^^^^
   |                                      |          |
   |                                      |          `webapi_client` is borrowed here
   |                                      may outlive borrowed value `webapi_client`

Therefore my question is if I should

  1. Wrap the Client in Arc nonetheless, e.g.
use std::sync::Arc;

async fn do_stuff(client : Arc<reqwest::Client>) {
    client.get("www.google.com").send().await;
}


#[tokio::main]
async fn main() -> tokio::io::Result<()> {

    let webapi_shared = Arc::new(reqwest::Client::new());
    let webapi_client = &*webapi_shared;

    let webapi_for_f1 = webapi_shared.clone();

    let webapi_for_f2 = webapi_shared.clone();

    let webapi1 = tokio::spawn(async move{do_stuff(webapi_for_f1).await});
    let webapi2 = tokio::spawn(async move{do_stuff(webapi_for_f2).await});

    webapi_client.get("www.google.com").send().await;

    webapi1.await;
    webapi2.await;

    Ok(())
}

  1. Just clone the client:
use std::sync::Arc;

async fn do_stuff(client : reqwest::Client) {
    client.get("www.google.com").send().await;
}


#[tokio::main]
async fn main() -> tokio::io::Result<()> {

    let webapi_client = reqwest::Client::new();

    let webapi_for_f1 = webapi_client.clone();

    let webapi_for_f2 = webapi_client.clone();

    let webapi1 = tokio::spawn(async move{do_stuff(webapi_for_f1).await});
    let webapi2 = tokio::spawn(async move{do_stuff(webapi_for_f2).await});

    webapi_client.get("www.google.com").send().await;

    webapi1.await;
    webapi2.await;

    Ok(())
}

…but I didn’t notice .clone() returning shallow copies 🙂

  1. Mitigate the lifetime issue some other way and just grab the reference? (any hints also welcome here)

>Solution :

…but I didn’t notice .clone() returning shallow copies 🙂

But that’s exactly what the docs you cited say:

You do not have to wrap the Client in an Rc or Arc to reuse it, because it already uses an Arc internally.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading