Time-manager of delayed tasks. Like crontab, but synchronous asynchronous tasks are possible, and dynamic add/cancel/remove is supported.

Overview

delay-timer

Build License Cargo Documentation

Time-manager of delayed tasks. Like crontab, but synchronous asynchronous tasks are possible, and dynamic add/cancel/remove is supported.

delay-timer is a task manager based on a time wheel algorithm, which makes it easy to manage timed tasks, or to periodically execute arbitrary tasks such as closures.

The underlying runtime is based on the optional smol and tokio, and you can build your application with either one.

The minimum-supported version of rustc is 1.49.

Except for the simple execution in a few seconds, you can also specify a specific date, such as Sunday at 4am to execute a backup task.

Supports configuration of the maximum number of parallelism of tasks.

image

Examples

#[macro_use]
use delay_timer::prelude::*;

use std::str::FromStr;
use std::sync::atomic::{
    AtomicUsize,
    Ordering::{Acquire, Release},
};
use std::sync::{atomic::AtomicI32, Arc};
use std::thread::{self, park_timeout};
use std::time::Duration;
use smol::Timer;
use hyper::{Client, Uri};

fn main() {
    let delay_timer = DelayTimerBuilder::default().build();

    // Add an asynchronous task to delay_timer.
    delay_timer.add_task(build_task(TaskBuilder::default()));

    // Since the tasks are executed in 8-second cycles,
    // we deal with something else.
    // Do someting about 8s.
    thread::sleep(Duration::new(8, 1_000_000));
    delay_timer.remove_task(1);
    delay_timer.stop_delay_timer();
}

fn build_task(mut task_builder: TaskBuilder) -> Task {
    let body = create_async_fn_body!({
        let mut res = surf::get("https://httpbin.org/get").await.unwrap();
        dbg!(res.body_string().await.unwrap());
    });

    task_builder
        .set_frequency_by_candy(CandyFrequency::Repeated(AuspiciousTime::PerEightSeconds))
        .set_task_id(2)
        .set_maximum_running_time(5)
        .spawn(body)
        .unwrap()
}

enum AuspiciousTime {
    PerSevenSeconds,
    PerEightSeconds,
    LoveTime,
}

impl Into<CandyCronStr> for AuspiciousTime {
    fn into(self) -> CandyCronStr {
        match self {
            Self::PerSevenSeconds => CandyCronStr("0/7 * * * * * *".to_string()),
            Self::PerEightSeconds => CandyCronStr("0/8 * * * * * *".to_string()),
            Self::LoveTime => CandyCronStr("0,10,15,25,50 0/1 * * Jan-Dec * 2020-2100".to_string()),
        }
    }
}

Capture the specified environment information and build the closure & task:

#[macro_use]
use delay_timer::prelude::*;

use std::str::FromStr;
use std::sync::atomic::{
    AtomicUsize,
    Ordering::{Acquire, Release},
};
use std::sync::{atomic::AtomicI32, Arc};
use std::thread::{self, park_timeout};
use std::time::Duration;
use smol::Timer;
use hyper::{Client, Uri};


let delay_timer = DelayTimer::new();

let share_num = Arc::new(AtomicUsize::new(0));
let share_num_bunshin = share_num.clone();

let body = create_async_fn_body!((share_num_bunshin){
    share_num_bunshin_ref.fetch_add(1, Release);
    Timer::after(Duration::from_secs(9)).await;
    share_num_bunshin_ref.fetch_sub(1, Release);
});

let task = TaskBuilder::default()
    .set_frequency_by_candy(CandyFrequency::CountDown(9, CandyCron::Secondly))
    .set_task_id(1)
    .set_maximun_parallel_runable_num(3)
    .spawn(body)
    .unwrap();

delay_timer.add_task(task).unwrap();

Building dynamic future tasks:

#[macro_use]
use delay_timer::prelude::*;

use std::str::FromStr;
use std::sync::atomic::{
    AtomicUsize,
    Ordering::{Acquire, Release},
};
use std::sync::{atomic::AtomicI32, Arc};
use std::thread::{self, park_timeout};
use std::time::Duration;
use smol::Timer;
use hyper::{Client, Uri};

fn build_task(mut task_builder: TaskBuilder) -> Task {
    let body = generate_closure_template(String::from("dynamic"));

    task_builder
        .set_frequency_by_candy(CandyFrequency::Repeated(AuspiciousTime::PerEightSeconds))
        .set_task_id(2)
        .set_maximum_running_time(5)
        .spawn(body)
        .unwrap()
}

pub fn generate_closure_template(
    name: String,
) -> impl Fn(TaskContext) -> Box<dyn DelayTaskHandler> + 'static + Send + Sync {
    move |context| {
        let future_inner = async_template(get_timestamp() as i32, name.clone());

        let future = async move {
            future_inner.await;
            context.finishe_task().await;
        };

        create_delay_task_handler(async_spawn_by_tokio(future))
    }
}

pub async fn async_template(id: i32, name: String) {
    let client = Client::new();

    let url = format!("http://httpbin.org/get?id={}&name={}", id, name);
     let uri: Uri = url.parse().unwrap();
     let res = client.get(uri).await.unwrap();
     println!("Response: {}", res.status());
     // Concatenate the body stream into a single buffer...
     let buf = hyper::body::to_bytes(res).await.unwrap();
     println!("body: {:?}", buf);
 }
 
 enum AuspiciousTime {
     PerSevenSeconds,
     PerEightSeconds,
     LoveTime,
 }

 impl Into<CandyCronStr> for AuspiciousTime {
     fn into(self) -> CandyCronStr {
         match self {
             Self::PerSevenSeconds => CandyCronStr("0/7 * * * * * *".to_string()),
             Self::PerEightSeconds => CandyCronStr("0/8 * * * * * *".to_string()),
             Self::LoveTime => CandyCronStr("0,10,15,25,50 0/1 * * Jan-Dec * 2020-2100".to_string()),
        }
    }
}

There's a lot more in the [examples] directory.

License

Licensed under either of

To Do List

  • Support tokio Ecology.
  • Disable unwrap related methods that will panic.
  • Thread and running task quit when delayTimer drop.
  • neaten todo in code, replenish tests and benchmark.
  • batch-opration.
  • report-for-server.
  • TASK-TAG.
  • Future upgrade of delay_timer to multi-wheel mode, different excutor handling different wheels e.g. subtract laps for one wheel, run task for one wheel.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

The author comments:

Make an upgrade plan for smooth updates in the future, Such as stop serve back-up unfinished task then up new version serve load task.bak, Runing.

Comments
  • Run task delay for an hour in UTC mode

    Run task delay for an hour in UTC mode

    Describe the bug Run task delay for an hour in UTC mode

    To Reproduce There are three task in a DelayTimerBuilder, two tasks run in time, but the first one task run delay for an hour.

    code:

            //delay_timer
            let delay_timer = DelayTimerBuilder::default()
                .tokio_runtime_by_default()
                .build();
    
            //Task1: renew symbols
            let body_renew_sym = create_async_fn_tokio_body!({
                if let Err(err) = base::init_symbol_list().await {
                    error!("Initial symbols list error: {}", err);
                }
            });
            let task_builder_renew_sym = TaskBuilder::default()
                .set_frequency_repeated_by_cron_str(&dotenv::var("50 00 22 * * * *").unwrap())
                .set_schedule_iterator_time_zone(ScheduleIteratorTimeZone::Utc)
                .set_task_id(1)
                //.set_maximum_running_time(600)
                .spawn(body_renew_sym)?;
            delay_timer.add_task(task_builder_renew_sym)?;
    
            //Task2: calculate D1 data and save to D1.csv file
            let body_d1 = create_async_fn_tokio_body!({
                csv::calculate_all_d1_ohlc();
            });
            let task_builder_d1 = TaskBuilder::default()
                .set_frequency_repeated_by_cron_str(&dotenv::var("0 10 22 * * Monday,Tuesday,Wednesday,Thursday,Friday *").unwrap())
                .set_schedule_iterator_time_zone(ScheduleIteratorTimeZone::Utc)
                .set_task_id(2)
                .spawn(body_d1)?;
            delay_timer.add_task(task_builder_d1)?;
    
            //Task4: calculate historical ohlc
            let body_ohlc = create_async_fn_tokio_body!((db_pool){
                if let Err(err) = csv::cron_sync_ohlc_to_db(&db_pool_ref).await {
                    error!("Cron sync ohlc to database error: {}", err);
                }
            });
            let task_builder_ohlc = TaskBuilder::default()
                .set_frequency_repeated_by_cron_str(&dotenv::var("0 20 22 * * Monday,Tuesday,Wednesday,Thursday,Friday *").unwrap())
                .set_schedule_iterator_time_zone(ScheduleIteratorTimeZone::Utc)
                .set_task_id(4)
                .spawn(body_ohlc)?;
            delay_timer.add_task(task_builder_ohlc)?;
    

    Info logs:

    2022-02-08T01:00:51.690533645+02:00 INFO sync::base::base - Get active symbol from http api, len= 870
    
    2022-02-08T00:20:00.484920457+02:00 INFO sync::csv::csv_file - Begin to sync cron calculate ohlc data and send to database...
    
    2022-02-08T00:10:00.484385080+02:00 INFO sync::csv::csv_file - Calculate D1 file from tick data file
    
    opened by rts-gordon 6
  • task parameter error

    task parameter error

    Describe the bug add parameters to task function will get error of lifetime.

    run example s demo.r,

    error[E0621]: explicit lifetime required in the type of `url`
      --> examples/demo.rs:81:10
       |
    81 |         .spawn(body)
       |          ^^^^^ lifetime `'static` required
    
    error[E0621]: explicit lifetime required in the type of `url`
      --> examples/demo.rs:68:16
       |
    68 |       let body = create_async_fn_body!({
       |  ________________^
    69 | |         if let Ok(mut res) = surf::get(url).await {
    70 | |             dbg!(res.body_string().await.unwrap_or_default());
    71 | |
    ...  |
    74 | |         }
    75 | |     });
       | |______^ lifetime `'static` required
       |
       = note: this error originates in the macro `create_async_fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
    
    documentation invalid 
    opened by bingryan 6
  • Set a daily 00:00:00 trigger task, from April 2 every day trigger time into 01::00:00

    Set a daily 00:00:00 trigger task, from April 2 every day trigger time into 01::00:00

    Describe the bug 设置了一个每天00:00:00触发的任务,从4月2号开始每天触发时间变成01::00:00了,不知道是否和时令有关.

    To Reproduce 程序从3月份开始运行,4月2号前都是正常触发的. 计时器设置: let task = TaskBuilder::default() .set_frequency_repeated_by_cron_str("0 0 0 * * * *") .set_task_id(1) .spawn_async_routine(body) .unwrap();

    Desktop (please complete the following information):

    • OS: Ubuntu 18.04 LTS
    • delay-timer :0.11.1
    • timezone: Asia/Shanghai
    • rustflags: ["--cfg", "unsound_local_offset"]
    opened by yuyidegit 5
  • 无法编译通过

    无法编译通过

    error[E0554]: #![feature] may not be used on the stable release channel --> /Users/lr/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/delay_timer-0.2.1/src/lib.rs:205:1 | 205 | #![feature(linked_list_cursors)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    error[E0554]: #![feature] may not be used on the stable release channel --> /Users/lr/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/delay_timer-0.2.1/src/lib.rs:206:1 | 206 | #![feature(doc_cfg)] | ^^^^^^^^^^^^^^^^^^^^

    error[E0658]: use of unstable library feature 'split_inclusive' --> /Users/lr/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/delay_timer-0.2.1/src/utils/parse.rs:149:52 | 149 | let mut sub_command_inner = command.trim().split_inclusive(angle_bracket).rev(); | ^^^^^^^^^^^^^^^ | = note: see issue #72360 https://github.com/rust-lang/rust/issues/72360 for more information

    error: aborting due to 3 previous errors

    Some errors have detailed explanations: E0554, E0658. For more information about an error, try rustc --explain E0554. error: could not compile delay_timer.

    opened by Ruilkyu 3
  • "set_frequency_once" always execute immediately.

    Describe the bug set_frequency_once_by_seconds(5) The function is executed immediately instead of being delayed for some time

    To Reproduce

    use std::time::Duration;
    
    use delay_timer::prelude::{DelayTimerBuilder, ScheduleIteratorTimeZone, TaskBuilder};
    
    #[tokio::main]
    async fn main() {
        let body = || async {
            println!("running: {}", chrono::Local::now());
        };
    
        println!("start: {}", chrono::Local::now());
        let new_task = TaskBuilder::default()
            .set_task_id(1)
            .set_schedule_iterator_time_zone(ScheduleIteratorTimeZone::Local)
            .set_frequency_once_by_seconds(5)
            .set_maximum_parallel_runnable_num(1)
            .spawn_async_routine(body)
            .unwrap();
    
        let delay_timer = DelayTimerBuilder::default().build();
        delay_timer.add_task(new_task).unwrap();
    
        tokio::time::sleep(Duration::from_secs(15)).await;
        println!("end: {}", chrono::Local::now());
    }
    
    delay_timer = { version = "0.11.0", features = ["status-report"] }
    chrono = "0.4.19"
    tokio = { version = "1", features = ["full"] }
    

    Result

    start: 2022-04-22 10:56:01.732017356 +08:00
    running: 2022-04-22 10:56:02.793417770 +08:00
    end: 2022-04-22 10:56:16.796830865 +08:00
    

    Expected behavior Expect a five-second delay.

    Desktop (please complete the following information):

    • OS: Linux version 3.10.0-957.el7.x86_64 (gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) )
    • Rust: rustc 1.59.0 (9d1b2106e 2022-02-23)
    opened by gamife 2
  • Scheduler running is not correct run in UTC/Local mode

    Scheduler running is not correct run in UTC/Local mode

    Hi @BinChengZhao There are some errors in UTC mode, would you like to have a look at this, thank you.

    Describe the bug Scheduler running is not correct in UTC mode

    To Reproduce define a task scheduler like this, run in UTC mode:

            let task_builder = TaskBuilder::default()
                .set_frequency_repeated_by_cron_str(&dotenv::var("0 15 06 * * * *“)
                .set_schedule_iterator_time_zone(ScheduleIteratorTimeZone::Utc)
                .set_task_id(1)
                .spawn(body)?;
    

    The task will be run one hour in advance(UTC: 05:15), also run in Local mode.

    Environment: Ubuntu Linux 20, delay_timer: main branch and feature/for_le_rust_156 branch.

    opened by rts-gordon 2
  • How to complete this demo with  delay-timer?

    How to complete this demo with delay-timer?

    Code is as follow, questions are in the code.

    Cargo.toml

    [dependencies]
    delay_timer = "0.10.1"
    

    main.rs

    
    use delay_timer::prelude::*;
    use anyhow::Result;
    use smol::Timer;
    use std::time::Duration;
    
    
    
    fn main() {
         //1、a timer start from 1 to 50000 millisecond.
                //let mut current_time= 1;
    
         //2、if the current_time equals some numbers, do somethings.
                if current_time =2000 {
                    //do something 1
                } 
                if current_time =39999 {
                    //do something 2
                } 
                //...
       
    }
    
    opened by zwl1619 2
  • build error

    build error

    error when build version 0.10.0

    cargo clean
    cargo update
    cargo build
    

    error message

    error[E0308]: mismatched types
       --> src/utils/parse.rs:308:9
        |
    308 |         Ok(process_linked_list)
        |         ^^^^^^^^^^^^^^^^^^^^^^^ expected enum `error::CommandChildError`, found struct `anyhow::Error`
        |
        = note: expected enum `std::result::Result<_, error::CommandChildError>`
                   found enum `std::result::Result<_, anyhow::Error>`
    
    For more information about this error, try `rustc --explain E0308`.
    error: could not compile `delay_timer` due to previous error
    
    
    opened by elderbig 2
  • Can not transmit args to shell

    Can not transmit args to shell

    Can not transmit args to shell I run a shell script for test,follow samples,like this:

    let body = unblock_process_task_fn("sh test_vars.sh>>try_spawn.txt".into());
    

    it can run well.

    I want put some arg into shell, then I rewrite like bellow:

    let body = unblock_process_task_fn("sh test_vars.sh>>try_spawn.txt  xxx".into());
    

    this is test_vars.sh

    t=`date`
    echo $t -- "I run [ $1 ]"
    

    The shell can run correct manualy,but nothing appeared,no message write into try_spawn.txt. I try another way use environment variable,like:

    let body = unblock_process_task_fn("TASK_ID=1 sh test_vars.sh>>try_spawn.txt".into());
    

    and script modify like this:

    t=`date`
    echo $t -- "I run [ $TASK_ID ]"
    
    opened by elderbig 2
  • examples/demo_async_std.rs  run error when duration 30s

    examples/demo_async_std.rs run error when duration 30s

    examples/demo_async_std.rs run error

    To Reproduce add a time to continue,like bellow

        thread::sleep(Duration::from_secs(20));
        Ok(delay_timer.stop_delay_timer()?)
    

    edit function build_task_async_execute_process() ,when shedule like "*/1 * * * * * *",it is run well.

    fn build_task_async_execute_process() -> Result<Task, TaskError> {
        let mut task_builder = TaskBuilder::default();
    
        let body = unblock_process_task_fn("ls -l >> ./try_spawn.txt".into());
        task_builder
            .set_task_id(3)
            .set_frequency_repeated_by_cron_str("*/1 * * * * * *")
            .set_maximum_running_time(10)
            .set_maximum_parallel_runnable_num(1)
            .spawn(body)
    

    when use schedule like "*/3 * * * * * *",that run task every 3 second, I got a error

    fn build_task_async_execute_process() -> Result<Task, TaskError> {
        let mut task_builder = TaskBuilder::default();
    
        let body = unblock_process_task_fn("ls -l >> ./try_spawn.txt".into());
        task_builder
            .set_task_id(3)
            .set_frequency_repeated_by_cron_str("*/3 * * * * * *")
            .set_maximum_running_time(10)
            .set_maximum_parallel_runnable_num(1)
            .spawn(body)
    

    error like this:

    create_async_fn_body!
    Error: TaskInstance event get failed.
    
    Caused by:
        receiving from an empty channel
    
    

    Desktop (please complete the following information):

    • OS: linux

    other Can you help me get more ditails for error?

    opened by elderbig 2
  • delay_timer rebuilds every time.

    delay_timer rebuilds every time.

    Describe the bug When cargo build is run on a project that depends on delay-timer, it will always rebuild, even if no changes have been made.

    To Reproduce Steps to reproduce the behavior:

    1. Create a new project with cargo new --bin test_proj
    2. Add delay_timer = "0.9.0" to the dependencies section of Cargo.toml
    3. Run cargo build multiple times in succession

    Every time cargo build is run, both delay_timer and the test_proj itself are recompiled.

    Expected behavior cargo build should not recompile anything if there have been no changes since the last compile.

    Screenshots N/A

    Desktop (please complete the following information):

    • OS: ubuntu 20
    • delay_timer version: 0.9.0
    opened by chaaz 2
  • set_frequency_repeated_by_cron_str cannot work

    set_frequency_repeated_by_cron_str cannot work

    set_frequency_repeated_by_cron_str cannot work, v0.11.3

    task_builder
        .set_task_id(1)
        .set_frequency_repeated_by_cron_str("@secondly")
        .set_maximum_parallel_runnable_num(1)
        .spawn_async_routine(body)
    

    only execute once, but set_frequency_repeated_by_seconds(1) works correctly

    opened by yulidai 1
  • Feature request: `DelayTimer` check if ID is in use

    Feature request: `DelayTimer` check if ID is in use

    Is your feature request related to a problem? Please describe. I'd like to be able to check if a task with a specific ID is already being handled by DelayTimer, so I can avoid overwriting accidentally by inserting a new task with the same ID

    Describe the solution you'd like

    impl DelayTimer {
        pub fn has_task(&self, id: u64) -> bool {
            todo!()
        }
    }
    

    Describe alternatives you've considered A workaround I considered was trying to remove a task then re-adding it if it existed, however DelayTimer::remove_task doesn't return the task being removed

    Additional context For use in my upcoming project

    opened by alpha-tango-kilo 4
  • How to set a microsecond interval for task

    How to set a microsecond interval for task

    Hi delay-timer guys, how to set a microsecond intervals for a task. From source-code, I can only find seconds-related function, and I can't use a cron string to generate a microsecond task, right?

    opened by KaitaoQiu 3
  • an error occurls when use delay-timer 0.10.0

    an error occurls when use delay-timer 0.10.0

    report an error when use delay-timer 0.10.0 I try run 1000 jobs in my program,ceveral minitue later,when process running, some error appeard

    2021-11-22T08:56:18.222587252+08:00 - INFO - src/main.rs -line=>29 - dt_test - ==== All job is be init! ====
    2021-11-22T08:56:30.354993232+08:00 - ERROR - /home/test/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/delay_timer-0.10.0/src/timer/event_handle.rs -line=>199 - delay_timer::timer::event_handle - Fn : `quit_one_task_handler`, No task-handle-index found (task-id: 453 , record-id: 6868351392860475493)
    2021-11-22T08:56:30.375546872+08:00 - ERROR - /home/test/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/delay_timer-0.10.0/src/timer/event_handle.rs -line=>199 - delay_timer::timer::event_handle - Fn : `quit_one_task_handler`, No task-handle-index found (task-id: 78 , record-id: 6868351392860475444)
    2021-11-22T08:56:30.380463067+08:00 - ERROR - /home/test/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/delay_timer-0.10.0/src/timer/event_handle.rs -line=>199 - delay_timer::timer::event_handle - Fn : `quit_one_task_handler`, No task-handle-index found (task-id: 561 , record-id: 6868351392860475452)
    2021-11-22T08:56:30.386620506+08:00 - ERROR - /home/test/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/delay_timer-0.10.0/src/timer/event_handle.rs -line=>199 - delay_timer::timer::event_handle - Fn : `quit_one_task_handler`, No task-handle-index found (task-id: 502 , record-id: 6868351392860475446)
    2021-11-22T08:56:30.394059243+08:00 - ERROR - /home/test/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/delay_timer-0.10.0/src/timer/event_handle.rs -line=>199 - delay_timer::timer::event_handle - Fn : `quit_one_task_handler`, No task-handle-index found (task-id: 37 , record-id: 6868351392860475469)
    2021-11-22T08:56:30.417319172+08:00 - ERROR - /home/test/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/delay_timer-0.10.0/src/timer/event_handle.rs -line=>199 - delay_timer::timer::event_handle - Fn : `quit_one_task_handler`, No task-handle-index found (task-id: 164 , record-id: 6868351392860475457)
    

    After this error,the program is still running,I can not know if there is some effection. my program

    #[async_std::main]
    async fn main() -> Result<()>{
        log4rs::init_file("conf/log4rs.yaml", Default::default()).unwrap();
        info!("begin");
        let delay_timer = DelayTimerBuilder::default().build();
        for i in 0..1000{
            let r = build_task_async_execute_process(i);
            match r {
                Ok(task) => {
                    let r = delay_timer.add_task(task);
                    match r {
                        Ok(_) => info!("init task id = [{}]", i),
                        Err(e) => info!("{}", e)
                    } 
                },
                Err(e)=> info!("{}", e)
            }
        }
        info!("==== All job is be init! ====");
        thread::sleep(Duration::from_secs(3600*6));
        Ok(delay_timer.stop_delay_timer()?)
    }
    
    fn build_task_async_execute_process(task_id:u64) -> Result<Task, TaskError> {
        let mut task_builder = TaskBuilder::default();
        let cmd_string = String::from("sh tester/test_script.sh");
        info!("cmd_string = [{}]", &cmd_string);
        let body = dt_functions::unblock_process_task_fn(cmd_string);
        task_builder
            .set_frequency_repeated_by_cron_str("* * * * * *".into())
            .set_task_id(task_id)
            .set_maximum_running_time(10)
            .set_maximum_parallel_runnable_num(1)
            .spawn(body)
    }
    

    also can see at my test project https://github.com/elderbig/delay_timer-test

    relevant issue #28

    opened by elderbig 3
  • Many jobs sometimes

    Many jobs sometimes

    Describe the bug

    #[async_std::main]
    async fn main() -> Result<()> {
        let conf = reader::read_config::read("conf/config.toml");
        log4rs::init_file("conf/log4rs.yaml", Default::default()).unwrap();
        let delay_timer = DelayTimerBuilder::default().build();
        let mut i:u64 = 0;
        for s in conf.service.unwrap() {
            i = i + 1;
            //If a task_id is used,new task will be ignore by insert_task fn.
            let begin_time = Local::now().naive_local();
            let shell_task_instance_chain = delay_timer.
                insert_task(build_task_async_execute_process(i,&s)?)?;
            let _ = shell_task_instance_chain
                .next_with_async_wait()
                .await?
                .cancel_with_async_wait()
                .await?;
            let end_time = Local::now().naive_local();
            info!("use [{0}] by task [{1}] init", (end_time - begin_time).num_seconds(), i);
        }
    
        info!("All job inited");
        for _ in 0..180 {
            thread::sleep(Duration::from_secs(60));
        }
        // No new tasks are accepted; running tasks are not affected.
        Ok(delay_timer.stop_delay_timer()?)
    }
    

    I config 100 jobs in a configuration file conf/config.toml,and init them in a loop,sometimes,it is remaining some jobs can not be init.output like:

    2021-11-17T19:06:56.221273177+08:00 - INFO - src/main.rs -line=>39 - testcron - use [1] by task [1] init
    2021-11-17T19:06:58.221268818+08:00 - INFO - src/main.rs -line=>39 - testcron - use [1] by task [2] init
    2021-11-17T19:06:56.221273177+08:00 - INFO - src/main.rs -line=>39 - testcron - use [1] by task [3] init
    2021-11-17T19:06:58.221268818+08:00 - INFO - src/main.rs -line=>39 - testcron - use [1] by task [4] init
    ....
    ....
    2021-11-17T19:07:00.221238386+08:00 - INFO - src/main.rs -line=>39 - testcron - use [1] by task [59] init
    2021-11-17T19:07:02.221417702+08:00 - INFO - src/main.rs -line=>39 - testcron - use [2] by task [60] init
    2021-11-17T19:07:04.221640690+08:00 - INFO - src/main.rs -line=>39 - testcron - use [2] by task [61] init
    2021-11-17T19:07:06.221278580+08:00 - INFO - src/main.rs -line=>39 - testcron - use [1] by task [62] init
    2021-11-17T19:07:08.221419039+08:00 - INFO - src/main.rs -line=>39 - testcron - use [2] by task [63] init
    2021-11-17T19:07:10.221318266+08:00 - INFO - src/main.rs -line=>39 - testcron - use [1] by task [64] init
    

    then,it do nothing for a long time,some remainding jobs not appeared any more.I try tokio, there is the same problem.

    opened by elderbig 18
  • Add more details when error

    Add more details when error

    No more detail informations when error LIke issue #25 I ment, I can not recive more information for debug. Trace information should be print when error appeared

    opened by elderbig 1
Releases(V0.11.2)
  • V0.11.2(May 9, 2022)

  • V0.11.1(Mar 6, 2022)

  • V0.11.0(Feb 11, 2022)

    Version 0.11.0

    Changed

    • Optimized the entire delay-timer usage by removing macros for creating asynchronous tasks and now allowing users to use a closure that returns a Future.

    • The default internal runtime currently used by 'Tokio', 'smol' can also be manually enabled by the user.

    • Updated lots of utility cases, lots of documentation, and dependency updates.

    • Fixed a bug where tasks were executed ahead of time.(#33)

    Details

    Major refactoring of 'task execution'.

    Source code(tar.gz)
    Source code(zip)
  • V0.10.0(Nov 19, 2021)

    Version 0.10.0

    Changed

    Optimized the use of internal time-wheel memory. (#28), thanks elderbig !

    Details

    There is a time-wheel in delay-timer, which is the carrier of all tasks.

    The time wheel uses slots (time scales) as units, each slot corresponds to a hash table, when a slot is rotated to it will execute the task that is already ready internally, when the task is executed it will move from one slot to another. In order to have enough capacity to store the tasks, there may be a memory allocation here, so that by the time the whole time wheel is traversed, each internal time wheel-slot will have rich memory capacity, and when there are many tasks the memory occupied by the whole time wheel will be very large. So it will be necessary to shrink the memory in time.

    This change is to shrink the memory in time after each round of training slots and executing tasks to ensure that the slots have a basic and compact capacity.

    Source code(tar.gz)
    Source code(zip)
  • V0.9.1(Oct 6, 2021)

  • V0.9.0(Oct 5, 2021)

    Version 0.9.0

    v0.9.0 New features:

    1. Add more user-friendly api for better experience!
    
      1.1. Gradually deprecating TaskBuilder api `set_frequency` & `set_frequency_by_candy`.
      
      1.2. Add more user-friendly api such as `set_frequency_once_by_timestamp_seconds` | `set_frequency_count_down_by_days` | `set_frequency_repeated_by_cron_str` these having better experience.
    

    Update dependency :

    Update cron_clock .
    

    Update examples:

    Change, async-std & tokio & demo & generic & increase use cases.
    

    Enriched Unit tests & documentation.

    Source code(tar.gz)
    Source code(zip)
  • V0.8.2(Sep 12, 2021)

    v0.8.2 New features:

    1. Optimization logic: After task removal, the surviving task instance resources can be cancelled normally.
    
    2. FIXED:
         When the `TimeoutTask` event fails to remove the handle, Ok(()) is returned by default.
         This causes the `TimeoutTask` event to be sent to the outside world by `status_report_sender`,Which is a buggy behavior.
    
    Source code(tar.gz)
    Source code(zip)
  • V0.8.0(Aug 25, 2021)

    v0.8.0 New features:

    1. Optimized the api for custom tokio runtime, better api definition, better experience.
    
      Api changes.
        1.  Added: `tokio_runtime_by_default` & `tokio_runtime_by_custom` & `tokio_runtime_shared_by_custom` .
    
        2. Private: `tokio_runtime`.
    
    2. Optimized the method of canceling task instances, no error log is recorded when canceling a task failure after timeout.
    
    3. Fix the compile error about `quit_one_task_handler` under nightly version.
    
    Source code(tar.gz)
    Source code(zip)
  • V0.7.1(Jul 16, 2021)

    Version 0.7.1

    v0.7.1 New features:

    1. Fix the bugs before V0.6.1, When receive a timeout event from the `sweeper`, it is possible that the task has been completed.
    So can't just call cancel.
    
      Two options fix it.
        1. `sweeper` Remove the recycling unit when the task is finished or cancelled.(Because rust's `BinaryHeap` does not support removing specific elements, this scheme is not used.)
    
        2. The public event is sent only after the internal event has been processed and succeeded. (Adopted.)
    
    2. Adjust api names (runnable -> runnable, maximun -> maximum).
    
    Source code(tar.gz)
    Source code(zip)
  • V0.6.1(Jun 12, 2021)

  • V0.6.0(Jun 9, 2021)

    v0.6.0 New features:

    1. Grouping errors associated with Task and TaskInstance and implementing the standard Error-Trait.
    
    2. Add `advance_task`-api to support users to manually trigger the execution of tasks..
    
    3. Add `get_*` api to `PublicFinishTaskBody` to support getting task_id or record_id or finish_time.
    
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(May 18, 2021)

    v0.5.0 New features:

    1. Remove all unwrap() calls.

    2. Redefined the errors exposed to the outside (encapsulated by thiserror) as libs to never expose anyhow::Error to the outside.

    2.1. Set separate TaskError. for Task-related operations. 2.2. Set separate HandleInstanceError. for Task-Instance-related operations.

    1. Optimized shell command parsing function, set exclusive pipeline for derived subprocesses -stderr.
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Apr 26, 2021)

    Release v0.4.0 .

    v0.4.0 New features:

    1. Support dynamic modification of running tasks.
    2. Support get handle `TaskInstancesChain` after insert task, and get running task instance `TaskInstance` dynamically.
    
      2.1. The task instance of a running task can be dynamically cancelled.
      2.2. There are three types of cancellation: synchronous blocking cancellation, time-out-limited cancellation, and asynchronous cancellation.
      2.3. Support reading the running status of running tasks.
    
    3. Support to get the output of internal asynchronous subtask process.
    

    Update dependency :

    Replace waitmap -> dashmap .
    Update cron_clock .
    

    Update examples:

    Add, async-std & tokio use cases.
    Add, dynamically cancel running task example case.
    

    Enriched documentation.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Feb 27, 2021)

  • v0.3.0(Feb 5, 2021)

    1.Compilable at stable by conditional compilation.

    2.Balancing performance and user experience (ajust CandyCronStr inner-type and add free-api for TaskBuilder).

    3.Support custom setting of time zone.

    4.Fix the clock too fast issue.

    5.Use next_second_hand to solve a schedule problem.

    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Jan 23, 2021)

    1.Enriched a large number of documents, more easy to use. 2.tokio-Runtime is supported. 3.Custom syntactic sugar for Cron expressions is supported, and the API is more friendly. 4.Optimize the internal logic, more secure execution. 5.task supports new features, you can set the maximum number of parallelism, and the task can automatically recycle the handle after completion. 6.Support status reporting, you can get the internal time by DelayTImer, and you can use the Cancel running task API now. 7.Generate more powerful macros for asynchronous task Body, more details you can find in the documentation and examples.

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Nov 11, 2020)

Owner
BinCheng
I'm a fan of the rust language, and I'm currently doing some work on distributed and base components.
BinCheng
Task runner and process manager for Rust

Steward Task runner and process manager for Rust. If you're not happy managing your infrastructure with a pile of bash scripts, this crate might be he

Alex Fedoseev 24 Dec 26, 2022
Ergo is a low-code IFTTT/Zapier style application, built with Rust and Svelte

Ergo is a low-code IFTTT/Zapier style application, built with Rust and Svelte. Tasks are customizable with Javascript and can contain state machines for more advanced task handling.

Daniel Imfeld 100 Dec 26, 2022
delicate A lightweight and distributed task scheduling platform written in rust

A lightweight and distributed task scheduling platform written in rust.

BinCheng 529 Jan 9, 2023
asynchronous and synchronous interfaces and persistence implementations for your OOD architecture

OOD Persistence Asynchronous and synchronous interfaces and persistence implementations for your OOD architecture Installation Add ood_persistence = {

Dmitriy Pleshevskiy 1 Feb 15, 2022
Alternative future adapters that provide cancel safety.

cancel-safe-futures Alternative futures adapters that are more cancel-safe. What is this crate? The futures library contains many adapters that make w

Oxide Computer Company 12 Jul 2, 2023
Like a cell, but make lifetimes dynamic instead of ownership

LendingCell is a mutable container that allows you to get an owned reference to the same object. When the owned reference is dropped, ownership return

Kalle Samuels 19 Dec 15, 2022
GaiaX dynamic template engine is a lightweight cross-platform solution for pure native dynamic card.

GaiaX dynamic template engine is a lightweight cross-platform solution for pure native dynamic card, developed by Alibaba YouKu technology team GaiaX

Alibaba 774 Dec 22, 2022
rust_arango enables you to connect with ArangoDB server, access to database, execute AQL query, manage ArangoDB in an easy and intuitive way, both async and plain synchronous code with any HTTP ecosystem you love.

rust_arango enables you to connect with ArangoDB server, access to database, execute AQL query, manage ArangoDB in an easy and intuitive way, both async and plain synchronous code with any HTTP ecosystem you love.

Foretag 3 Mar 24, 2022
OxHTTP is a very simple synchronous HTTP client and server

OxHTTP is a very simple synchronous implementation of HTTP 1.1 in Rust. It provides both a client and a server.

Oxigraph 13 Nov 29, 2022
A bit like tee, a bit like script, but all with a fake tty. Lets you remote control and watch a process

teetty teetty is a wrapper binary to execute a command in a pty while providing remote control facilities. This allows logging the stdout of a process

Armin Ronacher 259 Jan 3, 2023
GitHub Actions for mdBook (rust-lang/mdBook) ⚡️ Setup mdBook quickly and build your site fast. Linux (Ubuntu), macOS, and Windows are supported.

GitHub Actions for mdBook rust-lang/mdBook Setup Action. We can run mdBook on a virtual machine of GitHub Actions by this mdBook action. Linux, macOS,

Shohei Ueda 231 Jan 2, 2023
QueingSimulator is an application that can be used to build intuitions about behavior of synchronous request/reply systems

Queueing Simulator QueingSimulator is an application that can be used to build intuitions about behavior of synchronous request/reply systems (such as

Joe Magerramov 7 Sep 11, 2022
A synchronous HTTP server built on hyper.

Astra Astra is a synchronous HTTP server built on top of hyper. use astra::{Body, Response, Server}; fn main() { Server::bind("localhost:3000")

Ibraheem Ahmed 23 Nov 27, 2022
🎮 game loop + 🐷 coroutine + 🌯 burrito = 🚀🔥 blazingly synchronous async executor for games 🔥🚀

?? Koryto ?? Pronounced like corrito, which is pronounced as if you combined coroutine and burrito, because everyone knows coroutines are burritos in

Jakub Arnold 3 Jul 6, 2023
It's like "docker stats" but with beautiful, real-time charts into your terminal. 📊

?? ds - Real-time Stats with Terminal Charts Visualize container stats with beautiful, real-time charts directly in your terminal. Why ds? Missing Cha

Rafael R. Camargo 5 Oct 3, 2023
Czkawka is a simple, fast and easy to use app to remove unnecessary files from your computer.

Multi functional app to find duplicates, empty folders, similar images etc.

Rafał Mikrut 9.2k Jan 4, 2023
Modify fonts to remove bitmap and disable gridfit for Windows font rendering.

Since Windows 10 version 1703 (Creators Update), its built-in TrueType renderer now supports vertical anti-aliasing. Despite there are only 30 levels of grayscale shade, it dramatically improves text rendering, especially for CJK languages. Sadly, it is only enabled for selected fonts at selected sizes.

Star Brilliant 54 Dec 21, 2022
A lightweight and snappy crate to remove emojis from a string.

A lightweight and snappy crate to remove emojis from a string.

Tejas Ravishankar 8 Jul 19, 2022
swc is a super-fast compiler written in rust; producing widely-supported javascript from modern standards and typescript.

Make the web (development) faster. SWC (stands for Speedy Web Compiler) is a super-fast TypeScript / JavaScript compiler written in Rust. It's a libra

swc 25.4k Dec 31, 2022
Simple image metadata scrubber. Will remove EXIF, XMP and IPTC metadata.

Simple image metadata scrubber. Will remove EXIF, XMP and IPTC metadata.

Jae Lo Presti 12 Nov 29, 2022