Actix Cron으로 비동기 작업 예약이 쉬워졌습니다.

Cron은 단순히 지정된 간격으로 작업을 실행하는 스케줄링 데몬입니다. 우리는 일반적으로 데이터 백업, 보고서 생성, 백그라운드에서 설정 동기화 등에 cron을 사용합니다.

무엇을 배울 것인가 : -
  • Actix-web 설정.
  • 주기적인 작업에 대한 기간을 추가합니다.
  • 예약 유연성을 위해 cron 구문 분석기를 추가합니다.
  • cronjob을 사용하여 DB 작업을 수행합니다.

  • 필요한 라이브러리 :-

  • actix-web :- Rust를 위한 강력하고 실용적이며 매우 빠른 웹 프레임워크

  • reqwest :- 상위 수준 HTTP 클라이언트 라이브러리

  • actix-rt :- Actix 에코시스템을 위한 Tokio 기반 단일 스레드 비동기 런타임

  • cron :- cron 식 구문 분석기 및 일정 탐색기입니다.

  • chrono :- Rust용 날짜 및 시간 라이브러리

  • 1. Actix-web 설정



    Rust 프로젝트 초기화



    다음cargo new <file-name>으로 새 프로젝트를 시작합니다.

    기본 actix 서버 구현



    actix official docs 에서 샘플 코드를 복제해 보겠습니다.

    cargo.toml에 종속성 추가




    ....
    [dependencies]
    actix-web = "4"
    ....
    


    actix 서버용 코드를 작성해 봅시다.

    use actix_web::{web, App, HttpServer};
    
    #[actix_web::main]
    async fn main() -> std::io::Result<()> {
        HttpServer::new(|| {
            App::new()
                .route("/hello", web::get().to(|| async { "Hello World!" }))
        })
        .bind(("127.0.0.1", 8080))?
        .run()
        .await
    }
    


    2. 주기적 작업에 대한 기간 추가.




    use std::{collections::HashMap, time::Duration};
    use reqwest;
    use actix_rt::time;
    
    // async function to get data from url using reqwest library
    
    async fn get_ips() -> HashMap<String, String> {
        let resp = reqwest::get("https://httpbin.org/ip")
            .await.unwrap()
            .json::<HashMap<String, String>>()
            .await.unwrap();
        resp
    }
    
    async fn main() -> std::io::Result<()> {
    
      actix_rt::spawn(async {
          let mut interval = time::interval(Duration::from_secs(20));
          loop {
              interval.tick().await;
              let result = get_ips().await;
              println!("20 sec {:?}",result);
          }
      });
      ....
    }
    


    혼란스러운??



    아니, 헷갈릴 필요가 있다. 단계별 코드를 이해해 봅시다.

    actix_rt ()
    actix 시스템을 위한 tokio 기반 단일 스레드 비동기 런타임입니다.

    단일 스레드는 한 번에 하나의 명령만 실행됨을 의미합니다.

    actix_rt::spawn : 현재 스레드에 미래를 새 작업으로 생성합니다. 즉시 기다리지 않으면 JoinHandle::abort를 사용하여 작업을 취소할 수 있습니다(드롭할 때 현재 스레드를 분리함).

    actix_rt::spawn(async move {}) : move는 클로저의 환경 변수를 캡처하게 해줍니다.

    클로저는 단순한 익명 함수입니다.
    변수에 저장할 수 있으며 유형에 주석을 달 필요가 없습니다.

    tokio time::interval : 기간의 간격으로 산출되는 새로운 간격을 만듭니다. 첫 번째 틱이 즉시 완료됩니다.

  • interval.tick() : 간격의 다음 순간에 도달하면 완료됩니다.

  • Duration::from_secs(20) : 입력된 정수(초)로 새 Duration을 생성합니다.

    3. 일정 유연성을 위해 cron 파서를 추가합니다.



    use std::{collections::HashMap, time::Duration, str::FromStr};
    use chrono::{Local, FixedOffset};
    use cron::Schedule;
    use reqwest;
    use actix_rt::{self, time};
    
    use actix_web::{web, App, HttpServer};
    
    async fn get_ips() -> HashMap<String, String> {
        let resp = reqwest::get("https://httpbin.org/ip")
            .await.unwrap()
            .json::<HashMap<String, String>>()
            .await.unwrap();
        resp
    }
    
    #[actix_web::main] // or #[tokio::main]
    async fn main() -> std::io::Result<()> {
        actix_rt::spawn(async move {
            let expression = "1/50   *   *     *       *  *  *";
            let schedule = Schedule::from_str(expression).unwrap();
            let offset = Some(FixedOffset::east(0)).unwrap();
    
            loop {
                let mut upcoming = schedule.upcoming(offset).take(1);
                actix_rt::time::sleep(Duration::from_millis(500)).await;
                let local = &Local::now();
    
                if let Some(datetime) = upcoming.next() {
                    if datetime.timestamp() <= local.timestamp() {
    
                        let result = get_ips().await;
                        println!("{:?}",result);
                    }
                }
            }
        });
        HttpServer::new(|| {
            App::new()
                .route("/hello", web::get().to(|| async { "Hello World!" }))
        })
        .bind(("127.0.0.1", 8080))?
        .run()
        .await
    }
    

    여기서 무슨 새로운 일이 일어나고 있는지 이해하려고 노력합시다

    cron 식 : cron 패턴을 따릅니다. 그것에 대해 더 알고 싶다면 here .

    //                  sec  min   hour   day of month   month   day of week   year
      let expression = "0   30   9,12,15     1,15       May-Aug  Mon,Wed,Fri  2018/2";
    


    Schedule::from_str : IT가 문자열에서 값을 구문 분석합니다.

    FixedOffset : 고정 오프셋은 날짜 인스턴스를 만드는 데 사용됩니다. 양수 초는 북반구를 의미하고 음수 초는 서반구를 의미합니다.

    schedule.upcoming(offset).take(1) : coming은 오프셋 인스턴스를 가져오고 일정과 일치하는 DateTime 객체의 반복자를 반환합니다.

  • take : iterator의 첫 번째 항목을 반환합니다.

  • thread::sleep : 매 밀리초마다 조건을 확인하는 것은 우리의 사용 사례가 초 단위 이상이므로 이상적이지 않기 때문에 조건을 확인하기 전에 잠을 자야 합니다. cron에 대한 분 밀리초 제어를 원하면 더 낮은 시간을 시도할 수도 있습니다.

    Local::now() : 현지 시간대에 따라 현재 날짜 시간을 반환합니다.

    if let Some(datetime) = coming.next() {if datetime.timestamp() <= local.timestamp() {} } : iterator에서 datetime 객체를 찾고 local date time(current)이 >= iterator인 경우 그러면 함수가 실행됩니다.

    4. cronjob을 사용하여 DB 작업을 수행합니다.



    위의 두 가지와 마찬가지로 꽤 비슷합니다. 나는 당신이 스스로 이해할 수 있도록 엿볼 수 있고 예제 코드를 제공하려고 노력할 것입니다.

    우리는 DB 풀과 로거를 얻기 위해 함수 위에 clousure(move)를 사용할 것입니다.

    여기에서 코드를 찾으십시오. actix-question-bank-stackoverflow .

    cronjob에게 특별한 외침. 간단한 cron 스케줄러를 작성하도록 영감을 줍니다.

    GitHub에서 자유롭게 질문하고 변경 사항 및 제안을 요청하십시오.

    Github - Source Code

    해피해킹
    러스타시안!

    좋은 웹페이지 즐겨찾기