'How do I use a channel receiver inside a nested closure?

I want to share some data between an async function with another async function running on a separate thread. In this case it's a cronjob.

This is the solution I've come up with so far:

main.rs

use tokio::sync::mpsc;
use tokio::task;
use tokio_cron_scheduler::{Job, JobScheduler};


#[tokio::main]
pub async fn main() {
  let (tx, mut rx): (mpsc::Sender<i16>, mpsc::Receiver<i16>) = mpsc::channel(1000);

  task::spawn(async {
    let mut sched = JobScheduler::new();
    let job = Job::new_async("0 0/5 * * * *", |_uuid, _l| {
      Box::pin(async move {
        let devices = rx.recv().await.unwrap();
        api::insert_datapoint(devices).await;
      })
    }).unwrap();

    sched.add(job).expect("failed adding job to scheduler");
    sched.start().await.expect("failed starting scheduler");
  });
}

but I'm getting an error preventing me from doing so

cannot move out of `rx`, a captured variable in an `FnMut` closure
move out of `rx` occurs here (E0507)

Is there a way to solve this? Is my approach of using a channel for this task inherently wrong?

EDIT: I've tried adding the move keyword to the outermost closure, however this results in the same error

Adding a move before |_uuid, _l| does not make any difference either



Solution 1:[1]

I ended up getting it working thanks to cdhowie's suggestion

use tokio::task;
use tokio_cron_scheduler::{Job, JobScheduler};


#[tokio::main]
pub async fn main() {
  let (tx, rx): (async_channel::Sender<i16>, async_channel::Receiver<i16>) = async_channel::bounded(1000);

  task::spawn(async {
    let mut sched = JobScheduler::new();
    let job = Job::new_async("0 0/5 * * * *", |_uuid, _l| {
    let rx = rx.clone();
      Box::pin(async move {
        if let Ok(devices) = rx.recv.await {
          api::insert_datapoint(devices).await;
        }
      })
    }).unwrap();

    sched.add(job).expect("failed adding job to scheduler");
    sched.start().await.expect("failed starting scheduler");
  });
}

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 LBlend