'Actix Actor calling an async function (HTTP get request)

I have an actor that runs on a regular interval. It worked until I tried to add an HTTP request using reqwest

pub struct Scheduler;
impl actix::actor::Actor for Scheduler {
    type Context = Context<Self>;
    fn started(&mut self, ctx: &mut Context<Self>) {
        ctx.run_interval(Duration::from_secs(60), move |this, ctx| { this.announce(ctx, EVENT_NONE); });
    }
}
impl Scheduler {
    fn announce(&self, _ctx: &mut Context<Self>, event: &str) {
        //...
        let mut client = reqwest::blocking::Client::new().get("http://127.0.0.1:10080");
        let res = client.send(); 
        //...
    }
}

But I have the following error: Cannot drop a runtime in a context where blocking is not allowed. This happens when a runtime is dropped from within an asynchronous context. /home/me/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.17.0/src/runtime/blocking/shutdown.rs:51:21

From the message I think I should use async but I did not find a correct implementation. Can you help me?

Thanks in advance



Solution 1:[1]

I finally found 2 solutions:

Solution 1

pub struct Scheduler;
impl actix::actor::Actor for Scheduler {
  type Context = Context<Self>;
  fn started(&mut self, ctx: &mut Context<Self>) {
      ctx.run_interval(Duration::from_secs(60), move |this, ctx| { this.announce(ctx, EVENT_NONE); });
  }
}
impl Scheduler {
  fn announce(&self, ctx: &mut Context<Self>, event: &str) {
      //...
      self.send_announce(ctx, url, id); //outside the announce function because it is in a loop
      //...
  }
  fn send_announce(&self, _ctx: &mut Context<Self>, url:String, id: u32) {
      actix_web::rt::spawn(async move {
          let client = reqwest::Client::builder().build().expect("Cannot build web client");
          let res = client.get(&url).send().await;
          if res.is_ok() {
              info!("It works!");
          }
      }
  }
}

I don't know if it is the best way but it works

Solution 2

It is to use ureq as the HTTP client that is using a blocking I/O and I can call ctx.run_later.

Everything can stay in the announce() function

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1