【rust】tauri+tokio_cron_scheduler+reqwest:解决 "Cannot start a runtime from within a runtime"? 错误

问题背景

需要在tauri框架中引入tokio_cron_scheduler来处理定时任务,并在定时任务中发起http请求,但是在编码后总是由于tokio runtime 嵌套导致报错:"Cannot start a runtime from within a runtime",在查找资料后初步解决了。

参考:

Why does Tokio return the error "Cannot drop a runtime in a context where blocking is not allowed"?
How can I create a Tokio runtime inside another Tokio runtime without getting the error "Cannot start a runtime from within a runtime"?

代码:

use tauri::async_runtime::block_on;
use tokio::runtime::Handle;
use tokio_cron_scheduler::{JobScheduler, Job};
use reqwest::Client;



fn main() {
  let sched = block_on(initialize_cron_scheduler());
  // block_on(init_tokio_cron(sched.clone()));
  
  tauri::Builder::default()
  .manage(sched)
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

///
/// 使用第三方定时器库
/// 解决多个tokio线程嵌套的问题
/// https://stackoverflow.com/questions/65426683/why-does-tokio-return-the-error-cannot-drop-a-runtime-in-a-context-where-blocki
/// https://stackoverflow.com/questions/62536566/how-can-i-create-a-tokio-runtime-inside-another-tokio-runtime-without-getting-th
/// 
pub async fn initialize_cron_scheduler() -> JobScheduler {
  let cron_handler = JobScheduler::new().await.expect("Failed to initialize tokio cron handler");

  cron_handler.start().await.expect("Failed to start tokio cron handler");

  // 添加一个请求synching进行扫描的计时器
  let heart_job = Job::new("0/8 * * * * *", move |_uuid, _l| {
    let handle = Handle::current();
    tokio::task::spawn_blocking(|| {
      trigger_synching(handle);
    });
  }).unwrap();

  let job_id = cron_handler.add(heart_job).await.unwrap();

  cron_handler.clone()
}

// 主动触发synching程序扫描文件夹变更同步代码变更
fn trigger_synching(handle: Handle) {
  block_on(async {

      handle
          .spawn(async {

            let client = Client::builder()
            .danger_accept_invalid_certs(true)
            .build().unwrap();

            let res = client
            .post("http://127.0.0.1:8384/rest/db/scan?folder=zjfpn-yxrrm")
            .header("X-API-Key", "xxxxxxxxxxxxxxxxxxxxx")

            .send()
            .await;
        
            match res {
              Ok(response) => {
                println!("主动触发synching扫描文件: {}", response.status());
              }
              Err(err) => {
                println!("request error: {:?}", err);
              }
          }
          })
          .await
          .expect("Task spawned in Tokio executor panicked")

  })
}

 

posted @ 2023-02-14 13:53  newAdmin  阅读(468)  评论(0编辑  收藏  举报