zero4rs 2.0.0

zero4rs is a powerful, pragmatic, and extremely fast web framework for Rust
Documentation
use lazy_static::lazy_static;

use cron::Schedule;
use std::str::FromStr;

lazy_static! {
    pub static ref ONE_SEC: &'static str = "0/1 * * * * * *";
    pub static ref TWO_SEC: &'static str = "0/2 * * * * * *";
}

// ## crontab guru
// https://crontab.guru/
// ## React Cron widget
// https://recron.emptyui.com/doc/get-started
// --------------------------------------------------------------------------------------------------
//                  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";
// let expression = "0/2   *     *             *               *           *               *";
// --------------------------------------------------------------------------------------------------
pub async fn running<F>(expr: &str, period_millis: u64, f: F)
where
    F: Fn() + Send + 'static,
{
    let schedule = match Schedule::from_str(expr) {
        Ok(schedule) => {
            log::info!("start-a-looop: expr={}, func_name={}", expr, getname(&f));

            schedule
        }
        Err(err) => {
            log::error!(
                "Invalid time expression: func_name={}, error={:?}",
                getname(&f),
                err
            );
            return;
        }
    };

    let mut interval = tokio::time::interval(std::time::Duration::from_millis(period_millis));

    loop {
        let mut upcoming = schedule.upcoming(chrono::Utc).take(1);

        tokio::select! {
            // 等待下一个间隔
            _ = interval.tick() => {
                if let Some(datetime) = upcoming.next() {
                    if datetime.timestamp() <= chrono::Utc::now().timestamp() {
                        f();
                    }
                }
            }
            // 监听退出信号
            _ = tokio::signal::ctrl_c() => {
                log::info!("tokio::signal::ctrl_c() - 1");
                break;
            }
        }
    }
}

pub async fn interval<F>(period_millis: u64, f: F)
where
    F: Fn() + Send + 'static,
{
    let mut interval = tokio::time::interval(std::time::Duration::from_millis(period_millis));

    log::info!(
        "start-a-interval: period_millis={}, func_name={}",
        period_millis,
        getname(&f)
    );

    loop {
        tokio::select! {
            // 等待下一个间隔
            _ = interval.tick() => {
                f();
            }
            // 监听退出信号
            _ = tokio::signal::ctrl_c() => {
                log::info!("tokio::signal::ctrl_c() - 2");
                break;
            }
        }
    }
}

// 取得函数名
fn getname<F>(_: &F) -> &'static str
where
    F: Fn() + Send + 'static,
{
    std::any::type_name::<F>()
}