diff --git a/CHANGELOG.md b/CHANGELOG.md index fa37b18..e0022bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +# 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. # Version 0.8.2 v0.8.2 New features: diff --git a/Cargo.toml b/Cargo.toml index 7b56dc3..94656a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "delay_timer" -version = "0.8.3" +version = "0.9.0" authors = ["binchengZhao "] edition = "2018" repository = "https://github.com/BinChengZhao/delay-timer" @@ -29,7 +29,7 @@ status-report = [] [dependencies] -cron_clock = "0.7.0" +cron_clock = "0.8.0" anyhow = "^1.0.31" rs-snowflake = "0.5.0" dashmap = "^4.0.2" @@ -47,6 +47,7 @@ thiserror = "^1.0.24" tokio = { version = "^1.3.0", features = ["full"] , optional = true } [dev-dependencies] +rand = "0.8.4" surf = "^2.1.0" tokio = { version = "^1.3.0", features = ["full"] } hyper= {version = "^0.14.2" , features = ["full"] } diff --git a/README.md b/README.md index 8ede78a..c84b325 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ such as Sunday at 4am to execute a backup task. ![image](https://github.com/BinChengZhao/delay-timer/blob/master/structural_drawing/DelayTImer.png) +### If you're looking for a distributed task scheduling platform, check out the [delicate](https://github.com/BinChengZhao/delicate) + ## Examples @@ -69,7 +71,7 @@ fn build_task_async_print() -> Result { task_builder .set_task_id(1) - .set_frequency_by_candy(CandyFrequency::Repeated(CandyCron::Secondly)) + .set_frequency_repeated_by_seconds(1) .set_maximum_parallel_runnable_num(2) .spawn(body) } @@ -124,7 +126,7 @@ fn build_task_async_print() -> Result { task_builder .set_task_id(1) - .set_frequency(Frequency::Repeated("*/6 * * * * * *")) + .set_frequency_repeated_by_seconds(6) .set_maximum_parallel_runnable_num(2) .spawn(body) } @@ -156,7 +158,7 @@ fn build_task_async_print() -> Result { }); let task = TaskBuilder::default() - .set_frequency_by_candy(CandyFrequency::CountDown(9, CandyCron::Secondly)) + .set_frequency_count_down_by_seconds(1, 9) .set_task_id(1) .set_maximum_parallel_runnable_num(3) .spawn(body)?; @@ -178,7 +180,7 @@ fn build_task_customized_async_task() -> Result { let body = generate_closure_template("delay_timer is easy to use. .".into()); task_builder - .set_frequency_by_candy(CandyFrequency::Repeated(AuspiciousTime::LoveTime)) + .set_frequency_repeated_by_cron_str("0,10,15,25,50 0/1 * * Jan-Dec * 2020-2100") .set_task_id(5) .set_maximum_running_time(5) .spawn(body) @@ -206,21 +208,6 @@ pub async fn async_template(id: i32, name: String) -> Result<()> { Ok(()) } - enum AuspiciousTime { - PerSevenSeconds, - PerEightSeconds, - LoveTime, - } - - impl Into 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. @@ -240,7 +227,6 @@ Licensed under either of - [ ] neaten todo in code, replenish tests and benchmark. - [ ] batch-opration. - [x] 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 @@ -248,8 +234,3 @@ Licensed under either of 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. diff --git a/examples/cycle_tokio_task.rs b/examples/cycle_tokio_task.rs index 4b418cf..8fd2ade 100644 --- a/examples/cycle_tokio_task.rs +++ b/examples/cycle_tokio_task.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use anyhow::Result; use delay_timer::prelude::*; use hyper::{Client, Uri}; @@ -31,7 +33,7 @@ fn build_task_customized_async_task() -> Result { let body = generate_closure_template("'delay_timer-is-easy-to-use.'".into()); Ok(task_builder - .set_frequency_by_candy(CandyFrequency::Repeated(AuspiciousDay::Work)) + .set_frequency_repeated_by_cron_str("10,15,25,50 0/1 * * Jan-Dec * 2020-2100") .set_task_id(5) .set_maximum_running_time(15) .spawn(body)?) @@ -72,9 +74,9 @@ pub fn generate_closure_template( pub async fn async_template(id: i32, name: String) -> Result<()> { let client = Client::new(); - //The default connector does not handle TLS. - //Speaking to https destinations will require configuring a connector that implements TLS. - //So use http for test. + // The default connector does not handle TLS. + // Speaking to https destinations will require configuring a connector that implements TLS. + // So use http for test. let url = format!("http://httpbin.org/get?id={}&name={}", id, name); let uri: Uri = url.parse()?; @@ -87,14 +89,12 @@ pub async fn async_template(id: i32, name: String) -> Result<()> { } enum AuspiciousDay { - Work, Wake, } impl Into for AuspiciousDay { fn into(self) -> CandyCronStr { match self { - Self::Work => CandyCronStr("10,15,25,50 0/1 * * Jan-Dec * 2020-2100".to_string()), Self::Wake => CandyCronStr("0 * * * Jan-Dec * 2020-2100".to_string()), } } diff --git a/examples/demo.rs b/examples/demo.rs index 65b8fca..05405ad 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -55,7 +55,7 @@ fn build_task_async_print() -> Result { task_builder .set_task_id(1) - .set_frequency_by_candy(CandyFrequency::Repeated(CandyCron::Secondly)) + .set_frequency_repeated_by_cron_str("@secondly") .set_maximum_parallel_runnable_num(2) .spawn(body) } @@ -73,7 +73,7 @@ fn build_task_async_request() -> Result { }); task_builder - .set_frequency_by_candy(CandyFrequency::Repeated(AuspiciousTime::PerEightSeconds)) + .set_frequency_repeated_by_seconds(8) .set_task_id(2) .set_maximum_running_time(5) .spawn(body) @@ -84,7 +84,7 @@ fn build_task_async_execute_process() -> Result { let body = unblock_process_task_fn("php /home/open/project/rust/repo/myself/delay_timer/examples/try_spawn.php >> ./try_spawn.txt".into()); task_builder - .set_frequency_by_candy(CandyFrequency::Repeated(CandyCron::Minutely)) + .set_frequency_repeated_by_minutes(1) .set_task_id(3) .set_maximum_running_time(5) .spawn(body) @@ -94,6 +94,7 @@ fn build_task_customized_async_task() -> Result { let mut task_builder = TaskBuilder::default(); let body = generate_closure_template("delay_timer is easy to use. .".into()); + #[allow(deprecated)] task_builder .set_frequency_by_candy(CandyFrequency::Repeated(AuspiciousTime::LoveTime)) .set_task_id(5) @@ -133,7 +134,7 @@ fn build_wake_task() -> Result { }; task_builder - .set_frequency_by_candy(CandyFrequency::Repeated(CandyCron::Minutely)) + .set_frequency_repeated_by_cron_str("@minutely") .set_task_id(700) .set_maximum_running_time(50) .spawn(body) diff --git a/examples/demo_async_std.rs b/examples/demo_async_std.rs index 7159b67..8a24869 100644 --- a/examples/demo_async_std.rs +++ b/examples/demo_async_std.rs @@ -1,9 +1,9 @@ -use delay_timer::prelude::*; +#![allow(deprecated)] use anyhow::Result; - +use delay_timer::prelude::*; use smol::Timer; -use std::{ops::Deref, time::Duration}; +use std::time::Duration; // You can replace the 62 line with the command you expect to execute. #[async_std::main] @@ -47,11 +47,10 @@ fn build_task_async_print() -> Result { println!("create_async_fn_body:i'success"); }); - let s = String::from("*/6 * * * * * *"); - let s_r = (&s).deref(); + task_builder .set_task_id(1) - .set_frequency(Frequency::Repeated(s_r)) + .set_frequency_repeated_by_cron_str("*/6 * * * * * *") .set_maximum_parallel_runnable_num(2) .spawn(body) } diff --git a/examples/demo_async_tokio.rs b/examples/demo_async_tokio.rs index bfa58e7..bf72f8c 100644 --- a/examples/demo_async_tokio.rs +++ b/examples/demo_async_tokio.rs @@ -1,7 +1,5 @@ -use delay_timer::prelude::*; - use anyhow::Result; - +use delay_timer::prelude::*; use smol::Timer; use std::time::Duration; @@ -54,7 +52,7 @@ fn build_task_async_print() -> Result { task_builder .set_task_id(1) - .set_frequency(Frequency::Repeated("*/6 * * * * * *")) + .set_frequency_repeated_by_seconds(6) .set_maximum_parallel_runnable_num(2) .spawn(body) } @@ -64,7 +62,7 @@ fn build_task_async_execute_process() -> Result { let body = unblock_process_task_fn("php /home/open/project/rust/repo/myself/delay_timer/examples/try_spawn.php >> ./try_spawn.txt".into()); task_builder - .set_frequency_by_candy(CandyFrequency::Repeated(CandyCron::Secondly)) + .set_frequency_repeated_by_seconds(1) .set_task_id(3) .set_maximum_running_time(10) .set_maximum_parallel_runnable_num(1) diff --git a/examples/dynamic_cancel.rs b/examples/dynamic_cancel.rs index f04f8d8..5bb7167 100644 --- a/examples/dynamic_cancel.rs +++ b/examples/dynamic_cancel.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use anyhow::Result; use delay_timer::prelude::*; use smol::Timer; @@ -85,7 +87,7 @@ fn build_task_async_print() -> Result { task_builder .set_task_id(1) - .set_frequency(Frequency::Repeated("*/6 * * * * * *")) + .set_frequency_repeated_by_seconds(6) .set_maximum_parallel_runnable_num(2) .spawn(body) } @@ -95,7 +97,7 @@ fn build_task_async_execute_process() -> Result { let body = tokio_unblock_process_task_fn("php /home/open/project/rust/repo/myself/delay_timer/examples/try_spawn.php >> ./try_spawn.txt".into()); task_builder - .set_frequency_by_candy(CandyFrequency::Repeated(CandyCron::Secondly)) + .set_frequency_repeated_by_seconds(1) .set_task_id(3) .set_maximum_running_time(10) .set_maximum_parallel_runnable_num(1) diff --git a/examples/generic.rs b/examples/generic.rs index af08e17..88505f9 100644 --- a/examples/generic.rs +++ b/examples/generic.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use anyhow::Result; use delay_timer::prelude::*; use smol::Timer; @@ -43,7 +45,7 @@ fn build_generic_task_async_request(animal: T) -> Result>); @@ -44,7 +45,7 @@ fn main() -> AnyResult<()> { // The common task attr. task_builder - .set_frequency(Frequency::CountDown(1, "30 * * * * * *")) + .set_frequency_once_by_seconds(30) .set_maximum_running_time(90); for i in 0..1000 { @@ -52,7 +53,7 @@ fn main() -> AnyResult<()> { delay_timer.add_task(task)?; } - task_builder.set_frequency(Frequency::CountDown(1, "58 * * * * * *")); + task_builder.set_frequency_count_down_by_seconds(58, 1); for i in 1000..1300 { let task = task_builder.set_task_id(i).spawn(async_body)?; delay_timer.add_task(task)?; @@ -60,7 +61,7 @@ fn main() -> AnyResult<()> { let task = task_builder .set_task_id(8888) - .set_frequency(Frequency::CountDown(1, "@minutely")) + .set_frequency_once_by_minutes(1) .spawn(end_body)?; delay_timer.add_task(task)?; diff --git a/examples/profile_memory.rs b/examples/profile_memory.rs index 81a4802..0ac86a6 100644 --- a/examples/profile_memory.rs +++ b/examples/profile_memory.rs @@ -1,3 +1,4 @@ +#![allow(deprecated)] use delay_timer::prelude::*; use std::thread::sleep; use std::time::Duration; diff --git a/src/error.rs b/src/error.rs index 5d20a02..ccb88d1 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,7 +7,7 @@ use crate::prelude::*; pub enum TaskError { /// Error variant for Cron expression parsing. #[error("Cron expression analysis error.")] - CronExpressionAnalyzeError(#[from] CronExpressionAnalyzeError), + FrequencyAnalyzeError(#[from] FrequencyAnalyzeError), /// Task sending failure. #[error("Task sending failure.")] DisSend(#[from] channel::TrySendError), @@ -44,11 +44,14 @@ pub enum TaskInstanceError { /// Error enumeration for Cron expression parsing. #[derive(Error, Debug)] -pub enum CronExpressionAnalyzeError { +pub enum FrequencyAnalyzeError { /// Access to thread local storage failed. #[error("Thread local storage access failed.")] DisAccess(#[from] std::thread::AccessError), /// Irregular cron expressions that cause parsing failures. #[error("The cron expression was parsed incorrectly.")] DisParse(#[from] cron_error::Error), + /// The initialization time is wrong. + #[error("The initialization time is wrong.")] + DisInitTime, } diff --git a/src/lib.rs b/src/lib.rs index 5a8fd34..4959c9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,7 +67,7 @@ //! //! task_builder //! .set_task_id(1) -//! .set_frequency_by_candy(CandyFrequency::Repeated(CandyCron::Secondly)) +//! .set_frequency_repeated_by_seconds(1) //! .set_maximum_parallel_runnable_num(2) //! .spawn(body) //! } @@ -123,7 +123,7 @@ //! //! task_builder //! .set_task_id(1) -//! .set_frequency(Frequency::Repeated("*/6 * * * * * *")) +//! .set_frequency_repeated_by_seconds(6) //! .set_maximum_parallel_runnable_num(2) //! .spawn(body) //! } @@ -158,7 +158,7 @@ //! }); //! //! let task = TaskBuilder::default() -//! .set_frequency_by_candy(CandyFrequency::CountDown(9, CandyCron::Secondly)) +//! .set_frequency_count_down_by_seconds(1, 9) //! .set_task_id(1) //! .set_maximum_parallel_runnable_num(3) //! .spawn(body).expect(""); @@ -193,7 +193,7 @@ //! let body = generate_closure_template(String::from("dynamic")); //! //! task_builder -//! .set_frequency_by_candy(CandyFrequency::Repeated(AuspiciousTime::PerEightSeconds)) +//! .set_frequency_repeated_by_seconds(8) //! .set_task_id(2) //! .set_maximum_running_time(5) //! .spawn(body) @@ -227,21 +227,6 @@ //! Ok(()) //! } //! -//! enum AuspiciousTime { -//! PerSevenSeconds, -//! PerEightSeconds, -//! LoveTime, -//! } -//! -//! impl Into 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()), -//! } -//! } -//! } //! ``` #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)] #![cfg_attr(RUSTC_IS_NIGHTLY, feature(linked_list_cursors))] diff --git a/src/prelude.rs b/src/prelude.rs index bbdce44..a105068 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -17,7 +17,9 @@ pub use crate::timer::runtime_trace::state::instance; pub use crate::timer::runtime_trace::task_handle::DelayTaskHandler; pub use crate::timer::runtime_trace::task_instance::{Instance, TaskInstance, TaskInstancesChain}; pub use crate::timer::task::TaskContext; -pub use crate::timer::task::{Frequency, ScheduleIteratorTimeZone, Task, TaskBuilder}; +pub use crate::timer::task::{ + FrequencyCronStr as Frequency, ScheduleIteratorTimeZone, Task, TaskBuilder, +}; pub use crate::timer::timer_core::{FinishOutput, FinishTaskBody, TimerEvent}; pub use crate::utils::convenience::cron_expression_grammatical_candy::{ @@ -47,13 +49,17 @@ pub(crate) use crate::timer::runtime_trace::task_instance::TaskInstancesChainMai pub(crate) use crate::utils::parse::shell_command::{ChildGuard, ChildGuardList, ChildUnify}; pub(crate) use dashmap::DashMap; -pub(crate) use log::{error, info}; +pub(crate) use log::{debug, error, info, trace}; pub(crate) use smol::channel::{Receiver as AsyncReceiver, Sender as AsyncSender}; pub(crate) use smol::future::yield_now; pub(crate) use smol::lock::Mutex as AsyncMutex; pub(crate) use smol::Timer; +pub(crate) use std::convert::{TryFrom, TryInto}; +pub(crate) use std::iter::StepBy; +pub(crate) use std::ops::RangeFrom; pub(crate) use std::time::Duration; +pub(crate) type SecondsState = StepBy>; pub(crate) type TimerEventSender = AsyncSender; pub(crate) type TimerEventReceiver = AsyncReceiver; @@ -67,3 +73,8 @@ cfg_tokio_support!( cfg_status_report!( pub use crate::utils::status_report::PublicEvent; ); + +pub(crate) const ONE_SECOND: u64 = 1; +pub(crate) const ONE_MINUTE: u64 = ONE_SECOND * 60; +pub(crate) const ONE_HOUR: u64 = ONE_MINUTE * 60; +pub(crate) const ONE_DAY: u64 = ONE_HOUR * 24; diff --git a/src/timer/event_handle.rs b/src/timer/event_handle.rs index e9d9dd8..d6fa953 100644 --- a/src/timer/event_handle.rs +++ b/src/timer/event_handle.rs @@ -202,6 +202,8 @@ impl EventHandle { } pub(crate) async fn event_dispatch(&mut self, event: TimerEvent) -> Result { + trace!("event-dispatch: {:?}", event); + match event { TimerEvent::StopTimer => { self.shared_header.shared_motivation.store(false, Release); @@ -286,6 +288,7 @@ impl EventHandle { + second_hand; let slot_seed: u64 = time_seed % DEFAULT_TIMER_SLOT_COUNT; + let cylinder_line = time_seed / DEFAULT_TIMER_SLOT_COUNT; task.set_cylinder_line(time_seed / DEFAULT_TIMER_SLOT_COUNT); // copy task_id @@ -299,6 +302,10 @@ impl EventHandle { .set_task_id(task_id) .set_slot_mark(slot_seed) .set_parallel_runnable_num(0); + debug!( + "task-id: {} , next-exec-timestamp: {}, slot-seed: {}, cylinder-line: {}", + task_id, exec_time, slot_seed, cylinder_line + ); Ok(task_mart) } diff --git a/src/timer/mod.rs b/src/timer/mod.rs index 315214a..aab628e 100644 --- a/src/timer/mod.rs +++ b/src/timer/mod.rs @@ -1,10 +1,12 @@ //! timer is the core module of the library , it can provide an API for task building , //! task scheduling , event handling , resource recovery . + +pub mod task; +pub mod timer_core; + pub(crate) mod event_handle; pub(crate) mod runtime_trace; pub(crate) mod slot; -pub mod task; -pub mod timer_core; pub(crate) use slot::Slot; pub(crate) use task::{Task, TaskMark}; diff --git a/src/timer/task.rs b/src/timer/task.rs index 22d15f6..0024b16 100644 --- a/src/timer/task.rs +++ b/src/timer/task.rs @@ -54,21 +54,28 @@ impl TaskMark { #[inline(always)] pub(crate) fn set_parallel_runnable_num(&mut self, parallel_runnable_num: u64) -> &mut Self { + debug!( + "task-id: {}, parallel_runnable_num: {}", + self.task_id, self.parallel_runnable_num + ); self.parallel_runnable_num = parallel_runnable_num; self } #[inline(always)] pub(crate) fn inc_parallel_runnable_num(&mut self) { - self.parallel_runnable_num += 1; + let parallel_runnable_num = self.parallel_runnable_num + 1; + self.set_parallel_runnable_num(parallel_runnable_num); } #[inline(always)] pub(crate) fn dec_parallel_runnable_num(&mut self) { - self.parallel_runnable_num = self + let parallel_runnable_num = self .parallel_runnable_num .checked_sub(1) .unwrap_or_default(); + + self.set_parallel_runnable_num(parallel_runnable_num); } #[inline(always)] @@ -131,30 +138,122 @@ impl TaskMark { } #[derive(Debug, Copy, Clone)] -/// Enumerated values of repeating types. -pub enum Frequency<'a> { +pub(crate) enum FrequencyUnify<'a> { + FrequencyCronStr(FrequencyCronStr<'a>), + FrequencySeconds(FrequencySeconds), +} + +impl<'a> Default for FrequencyUnify<'a> { + fn default() -> FrequencyUnify<'a> { + FrequencyUnify::FrequencySeconds(FrequencySeconds::default()) + } +} + +#[derive(Debug, Copy, Clone)] +/// Enumerated values of repeating types based on the string of cron-expression. +pub enum FrequencyCronStr<'a> { /// Repeat once. Once(&'a str), /// Repeat ad infinitum. Repeated(&'a str), /// Type of countdown. - CountDown(u32, &'a str), + CountDown(u64, &'a str), +} + +#[derive(Debug, Copy, Clone)] +/// Enumerated values of repeating types based on the number of seconds. +pub(crate) enum FrequencySeconds { + /// Repeat once. + Once(u64), + /// Repeat ad infinitum. + Repeated(u64), + /// Type of countdown. + CountDown(u64, u64), +} + +impl<'a> Default for FrequencyCronStr<'a> { + fn default() -> FrequencyCronStr<'a> { + FrequencyCronStr::Once("@minutely") + } } -impl<'a> Default for Frequency<'a> { - fn default() -> Frequency<'a> { - Frequency::Once("@minutely") +impl Default for FrequencySeconds { + fn default() -> FrequencySeconds { + FrequencySeconds::Once(ONE_MINUTE) } } /// Iterator for task internal control of execution time. #[derive(Debug, Clone)] pub(crate) enum FrequencyInner { - ///Unlimited repetition types. - Repeated(DelayTimerScheduleIteratorOwned), - ///Type of countdown. - CountDown(u32, DelayTimerScheduleIteratorOwned), + /// Unlimited repetition types for cron-expression. + CronExpressionRepeated(DelayTimerScheduleIteratorOwned), + /// Type of countdown for cron-expression. + CronExpressionCountDown(u64, DelayTimerScheduleIteratorOwned), + /// Unlimited repetition types for seconds-duration. + SecondsRepeated(SecondsState), + /// Type of countdown for SecondsState. + /// SecondsCountDown(count_down, SecondsState) + SecondsCountDown(u64, SecondsState), +} + +impl<'a> TryFrom<(FrequencyUnify<'a>, ScheduleIteratorTimeZone)> for FrequencyInner { + type Error = FrequencyAnalyzeError; + + fn try_from( + (frequency, time_zone): (FrequencyUnify<'_>, ScheduleIteratorTimeZone), + ) -> Result { + let frequency_inner = match frequency { + FrequencyUnify::FrequencyCronStr(FrequencyCronStr::Once(cron_str)) => { + let task_schedule = + DelayTimerScheduleIteratorOwned::analyze_cron_expression(time_zone, cron_str)?; + + FrequencyInner::CronExpressionCountDown(1, task_schedule) + } + FrequencyUnify::FrequencyCronStr(FrequencyCronStr::Repeated(cron_str)) => { + let task_schedule = + DelayTimerScheduleIteratorOwned::analyze_cron_expression(time_zone, cron_str)?; + + FrequencyInner::CronExpressionRepeated(task_schedule) + } + FrequencyUnify::FrequencyCronStr(FrequencyCronStr::CountDown(count_down, cron_str)) => { + let task_schedule = + DelayTimerScheduleIteratorOwned::analyze_cron_expression(time_zone, cron_str)?; + + FrequencyInner::CronExpressionCountDown(count_down as u64, task_schedule) + } + + FrequencyUnify::FrequencySeconds(FrequencySeconds::Once(seconds)) => { + if seconds == 0 { + return Err(FrequencyAnalyzeError::DisInitTime); + } + + let seconds_state: SecondsState = (get_timestamp()..).step_by(seconds as usize); + FrequencyInner::SecondsCountDown(1, seconds_state) + } + FrequencyUnify::FrequencySeconds(FrequencySeconds::Repeated(seconds)) => { + if seconds == 0 { + return Err(FrequencyAnalyzeError::DisInitTime); + } + + let seconds_state: SecondsState = (get_timestamp()..).step_by(seconds as usize); + + FrequencyInner::SecondsRepeated(seconds_state) + } + FrequencyUnify::FrequencySeconds(FrequencySeconds::CountDown(count_down, seconds)) => { + if seconds == 0 { + return Err(FrequencyAnalyzeError::DisInitTime); + } + + let seconds_state: SecondsState = (get_timestamp()..).step_by(seconds as usize); + FrequencyInner::SecondsCountDown(count_down, seconds_state) + } + }; + + Ok(frequency_inner) + } } + /// Set the time zone for the time of the expression iteration. #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] pub enum ScheduleIteratorTimeZone { @@ -259,7 +358,7 @@ impl DelayTimerScheduleIteratorOwned { fn analyze_cron_expression( time_zone: ScheduleIteratorTimeZone, cron_expression: &str, - ) -> Result { + ) -> Result { let indiscriminate_expression = cron_expression.trim_matches(' ').to_owned(); let schedule_iterator_time_zone_query: ScheduleIteratorTimeZoneQuery = ScheduleIteratorTimeZoneQuery { @@ -292,34 +391,45 @@ impl DelayTimerScheduleIteratorOwned { } impl FrequencyInner { - //How many times the acquisition needs to be performed. + // How many times the acquisition needs to be performed. #[allow(dead_code)] - fn residual_time(&self) -> u32 { + fn residual_time(&self) -> u64 { match self { - FrequencyInner::Repeated(_) => u32::MAX, - FrequencyInner::CountDown(ref time, _) => *time, + FrequencyInner::CronExpressionRepeated(_) => u64::MAX, + FrequencyInner::SecondsRepeated(_) => u64::MAX, + FrequencyInner::CronExpressionCountDown(ref time, _) => *time, + FrequencyInner::SecondsCountDown(ref time, _) => *time, } } fn next_alarm_timestamp(&mut self) -> Option { match self { - FrequencyInner::CountDown(_, ref mut clock) => clock.next(), - FrequencyInner::Repeated(ref mut clock) => clock.next(), + FrequencyInner::CronExpressionCountDown(_, ref mut clock) => clock.next(), + FrequencyInner::CronExpressionRepeated(ref mut clock) => clock.next(), + FrequencyInner::SecondsRepeated(seconds_state) => { + seconds_state.next().map(|s| s as i64) + } + FrequencyInner::SecondsCountDown(_, seconds_state) => { + seconds_state.next().map(|s| s as i64) + } } } #[warn(unused_parens)] fn down_count(&mut self) { match self { - FrequencyInner::CountDown(ref mut exec_count, _) => { - *exec_count -= 1u32; - } - FrequencyInner::Repeated(_) => {} + FrequencyInner::CronExpressionRepeated(_) => {} + FrequencyInner::SecondsRepeated(_) => {} + FrequencyInner::CronExpressionCountDown(ref mut exec_count, _) => *exec_count -= 1u64, + FrequencyInner::SecondsCountDown(count_down, _) => *count_down -= 1u64, }; } fn is_down_over(&mut self) -> bool { - !matches!(self, FrequencyInner::CountDown(0, _)) + matches!( + self, + FrequencyInner::CronExpressionCountDown(0, _) | FrequencyInner::SecondsCountDown(0, _) + ) } } @@ -328,7 +438,7 @@ impl FrequencyInner { /// Cycle plan task builder. pub struct TaskBuilder<'a> { /// Repeat type. - frequency: Frequency<'a>, + frequency: FrequencyUnify<'a>, /// Task_id should unique. task_id: u64, @@ -430,35 +540,35 @@ pub struct Task { pub(crate) maximum_parallel_runnable_num: Option, } -//bak type BoxFn -// type BoxFn = Box Pin>>>; - -enum RepeatType { - Num(u32), - Always, -} - impl<'a> TaskBuilder<'a> { /// Set task Frequency. + /// This api will be deprecated in the future, please use `set_frequency_once_*` | `set_frequency_count_down_*` | `set_frequency_repeated_*` etc. + #[deprecated] #[inline(always)] pub fn set_frequency(&mut self, frequency: Frequency<'a>) -> &mut Self { - self.frequency = frequency; + self.frequency = FrequencyUnify::FrequencyCronStr(frequency); self } /// Set task Frequency by customized CandyCronStr. /// In order to build a high-performance, /// highly reusable `TaskBuilder` that maintains the Copy feature . + /// /// when supporting building from CandyCronStr , /// here actively leaks memory for create a str-slice (because str-slice support Copy, String does not) + /// /// We need to call `free` manually before `TaskBuilder` drop or before we leave the scope. /// /// Explain: /// Explicitly implementing both `Drop` and `Copy` trait on a type is currently - /// disallowed. This feature can make some sense in theory, but the current + /// disallowed. + /// + /// This feature can make some sense in theory, but the current /// implementation is incorrect and can lead to memory unsafety (see /// (issue #20126), so it has been disabled for now. + /// This api will be deprecated in the future, please use `set_frequency_*_by_candy` etc. + #[deprecated] #[inline(always)] pub fn set_frequency_by_candy>( &mut self, @@ -474,12 +584,12 @@ impl<'a> TaskBuilder<'a> { Frequency::Repeated(Box::leak(candy_cron_middle_str.into().0.into_boxed_str())) } CandyFrequency::CountDown(exec_count, candy_cron_middle_str) => Frequency::CountDown( - exec_count, + exec_count as u64, Box::leak(candy_cron_middle_str.into().0.into_boxed_str()), ), }; - self.frequency = frequency; + self.frequency = FrequencyUnify::FrequencyCronStr(frequency); self } @@ -522,27 +632,7 @@ impl<'a> TaskBuilder<'a> { where F: Fn(TaskContext) -> Box + 'static + Send + Sync, { - let frequency_inner; - - // The user inputs are pattern matched for different repetition types. - let (expression_str, repeat_type) = match self.frequency { - Frequency::Once(expression_str) => (expression_str, RepeatType::Num(1)), - Frequency::Repeated(expression_str) => (expression_str, RepeatType::Always), - Frequency::CountDown(exec_count, expression_str) => { - (expression_str, RepeatType::Num(exec_count)) - } - }; - - let taskschedule = DelayTimerScheduleIteratorOwned::analyze_cron_expression( - self.schedule_iterator_time_zone, - expression_str, - )?; - - // Building TaskFrequencyInner patterns based on repetition types. - frequency_inner = match repeat_type { - RepeatType::Always => FrequencyInner::Repeated(taskschedule), - RepeatType::Num(repeat_count) => FrequencyInner::CountDown(repeat_count, taskschedule), - }; + let frequency_inner = (self.frequency, self.schedule_iterator_time_zone).try_into()?; let body = SafeStructBoxedFn(Box::new(body)); @@ -570,9 +660,10 @@ impl<'a> TaskBuilder<'a> { pub fn free(&mut self) { if self.build_by_candy_str { let s = match self.frequency { - Frequency::Once(s) => s, - Frequency::Repeated(s) => s, - Frequency::CountDown(_, s) => s, + FrequencyUnify::FrequencyCronStr(Frequency::Once(s)) => s, + FrequencyUnify::FrequencyCronStr(Frequency::Repeated(s)) => s, + FrequencyUnify::FrequencyCronStr(Frequency::CountDown(_, s)) => s, + _ => return, }; unsafe { @@ -582,6 +673,185 @@ impl<'a> TaskBuilder<'a> { } } +impl<'a> TaskBuilder<'a> { + /// Task execution frequency: execute only once, set by cron expression. + #[inline(always)] + pub fn set_frequency_once_by_cron_str(&mut self, cron_str: &'a str) -> &mut Self { + self.frequency = FrequencyUnify::FrequencyCronStr(FrequencyCronStr::Once(cron_str)); + self + } + + /// Task execution frequency: countdown execution, set by cron expression. + #[inline(always)] + pub fn set_frequency_repeated_by_cron_str(&mut self, cron_str: &'a str) -> &mut Self { + self.frequency = FrequencyUnify::FrequencyCronStr(FrequencyCronStr::Repeated(cron_str)); + self + } + + /// Task execution frequency: execute repeatedly, set by cron expression. + #[inline(always)] + pub fn set_frequency_count_down_by_cron_str( + &mut self, + cron_str: &'a str, + count_down: u64, + ) -> &mut Self { + self.frequency = + FrequencyUnify::FrequencyCronStr(FrequencyCronStr::CountDown(count_down, cron_str)); + self + } + + /// Task execution frequency: execute only once, set by seconds num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + #[inline(always)] + pub fn set_frequency_once_by_seconds(&mut self, seconds: u64) -> &mut Self { + self.frequency = FrequencyUnify::FrequencySeconds(FrequencySeconds::Once(seconds)); + self + } + + /// Task execution frequency: countdown execution, set by seconds num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + #[inline(always)] + pub fn set_frequency_repeated_by_seconds(&mut self, seconds: u64) -> &mut Self { + self.frequency = FrequencyUnify::FrequencySeconds(FrequencySeconds::Repeated(seconds)); + self + } + + /// Task execution frequency: execute repeatedly, set by seconds num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + #[inline(always)] + pub fn set_frequency_count_down_by_seconds( + &mut self, + seconds: u64, + count_down: u64, + ) -> &mut Self { + self.frequency = + FrequencyUnify::FrequencySeconds(FrequencySeconds::CountDown(count_down, seconds)); + self + } + + /// Task execution frequency: execute only once, set by minutes num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + pub fn set_frequency_once_by_minutes(&mut self, minutes: u64) -> &mut Self { + self.frequency = + FrequencyUnify::FrequencySeconds(FrequencySeconds::Once(ONE_MINUTE * minutes)); + self + } + + /// Task execution frequency: countdown execution, set by minutes num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + #[inline(always)] + pub fn set_frequency_repeated_by_minutes(&mut self, minutes: u64) -> &mut Self { + self.frequency = + FrequencyUnify::FrequencySeconds(FrequencySeconds::Repeated(ONE_MINUTE * minutes)); + self + } + + /// Task execution frequency: execute repeatedly, set by minutes num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + #[inline(always)] + pub fn set_frequency_count_down_by_minutes( + &mut self, + minutes: u64, + count_down: u64, + ) -> &mut Self { + self.frequency = FrequencyUnify::FrequencySeconds(FrequencySeconds::CountDown( + count_down, + ONE_MINUTE * minutes, + )); + self + } + + /// Task execution frequency: execute only once, set by hours num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + pub fn set_frequency_once_by_hours(&mut self, hours: u64) -> &mut Self { + self.frequency = FrequencyUnify::FrequencySeconds(FrequencySeconds::Once(ONE_HOUR * hours)); + self + } + + /// Task execution frequency: execute repeatedly, set by hours num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + #[inline(always)] + pub fn set_frequency_repeated_by_hours(&mut self, hours: u64) -> &mut Self { + self.frequency = + FrequencyUnify::FrequencySeconds(FrequencySeconds::Repeated(ONE_HOUR * hours)); + self + } + + /// Task execution frequency: countdown execution, set by hours num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + #[inline(always)] + pub fn set_frequency_count_down_by_hours(&mut self, hours: u64, count_down: u64) -> &mut Self { + self.frequency = FrequencyUnify::FrequencySeconds(FrequencySeconds::CountDown( + count_down, + ONE_HOUR * hours, + )); + self + } + + /// Task execution frequency: execute only once, set by days num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + pub fn set_frequency_once_by_days(&mut self, days: u64) -> &mut Self { + self.frequency = FrequencyUnify::FrequencySeconds(FrequencySeconds::Once(ONE_DAY * days)); + self + } + + /// Task execution frequency: execute repeatedly, set by days num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + #[inline(always)] + pub fn set_frequency_repeated_by_days(&mut self, days: u64) -> &mut Self { + self.frequency = + FrequencyUnify::FrequencySeconds(FrequencySeconds::Repeated(ONE_DAY * days)); + self + } + + /// Task execution frequency: countdown execution, set by days num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + #[inline(always)] + pub fn set_frequency_count_down_by_days(&mut self, days: u64, count_down: u64) -> &mut Self { + self.frequency = FrequencyUnify::FrequencySeconds(FrequencySeconds::CountDown( + count_down, + ONE_DAY * days, + )); + self + } + + /// Task execution frequency: execute only once, set by timestamp-seconds num. + /// + /// Make sure time is greater than 1 seconds, otherwise undefined behavior will be triggered. + + pub fn set_frequency_once_by_timestamp_seconds(&mut self, timestamp_seconds: u64) -> &mut Self { + let duration = timestamp_seconds + .checked_sub(get_timestamp()) + .unwrap_or(ONE_SECOND); + + self.frequency = FrequencyUnify::FrequencySeconds(FrequencySeconds::Once(duration)); + self + } +} impl Task { // get SafeBoxFn of Task to call. #[inline(always)] @@ -598,16 +868,16 @@ impl Task { self.is_valid() } - //down_exec_count + // down_exec_count #[inline(always)] fn down_count(&mut self) { self.frequency.down_count(); } - //set_valid_by_count_down + // set_valid_by_count_down #[inline(always)] fn set_valid_by_count_down(&mut self) { - self.valid = self.frequency.is_down_over(); + self.valid = !self.frequency.is_down_over(); } #[inline(always)] @@ -672,35 +942,184 @@ impl Task { } } +#[cfg(test)] mod tests { - #[allow(unused_imports)] + #![allow(deprecated)] + + use super::{Task, TaskBuilder}; + use crate::prelude::*; + use crate::utils::convenience::functions::create_default_delay_task_handler; use anyhow::Result as AnyResult; + use rand::prelude::*; + use std::iter::Iterator; #[test] fn test_task_valid() -> AnyResult<()> { - use super::{Frequency, Task, TaskBuilder}; - use crate::utils::convenience::functions::create_default_delay_task_handler; let mut task_builder = TaskBuilder::default(); - //The third run returns to an invalid state. - task_builder.set_frequency(Frequency::CountDown(3, "* * * * * * *")); + // The third run returns to an invalid state. + task_builder.set_frequency_count_down_by_seconds(1, 3); let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; assert!(task.down_count_and_set_vaild()); assert!(task.down_count_and_set_vaild()); assert!(!task.down_count_and_set_vaild()); + task_builder.set_frequency_count_down_by_cron_str("* * * * * * *", 3); + let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; + + assert!(task.down_count_and_set_vaild()); + assert!(task.down_count_and_set_vaild()); + assert!(!task.down_count_and_set_vaild()); + + Ok(()) + } + + #[test] + fn test_get_next_exec_timestamp_seconds() -> AnyResult<()> { + let mut rng = rand::thread_rng(); + let init_seconds: u64 = rng.gen_range(1..100_00_00); + let mut task_builder = TaskBuilder::default(); + + task_builder.set_frequency_count_down_by_seconds(init_seconds, 3); + let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; + + (1..100) + .map(|i| { + debug_assert_eq!( + task.get_next_exec_timestamp().unwrap(), + get_timestamp() + (init_seconds * (i - 1)) + ); + }) + .for_each(drop); + + task_builder.set_frequency_count_down_by_cron_str("* * * * * * *", 100); + let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; + + (1..100) + .map(|_| { + assert!(task.down_count_and_set_vaild()); + }) + .for_each(drop); + + assert!(!task.down_count_and_set_vaild()); + + Ok(()) + } + + #[test] + fn test_get_next_exec_timestamp_minutes() -> AnyResult<()> { + let mut rng = rand::thread_rng(); + let init_minutes: u64 = rng.gen_range(1..100_00_00); + let mut task_builder = TaskBuilder::default(); + + task_builder.set_frequency_repeated_by_minutes(init_minutes); + let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; + + (1..100) + .map(|i| { + debug_assert_eq!( + task.get_next_exec_timestamp().unwrap(), + get_timestamp() + (init_minutes * (i - 1) * ONE_MINUTE) + ); + }) + .for_each(drop); + + Ok(()) + } + + #[test] + fn test_get_next_exec_timestamp_hours() -> AnyResult<()> { + let mut rng = rand::thread_rng(); + let init_hours: u64 = rng.gen_range(1..100_00_00); + let mut task_builder = TaskBuilder::default(); + + task_builder.set_frequency_repeated_by_hours(init_hours); + let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; + + (1..100) + .map(|i| { + debug_assert_eq!( + task.get_next_exec_timestamp().unwrap(), + get_timestamp() + (init_hours * (i - 1) * ONE_HOUR) + ); + }) + .for_each(drop); + + Ok(()) + } + + #[test] + fn test_get_next_exec_timestamp_days() -> AnyResult<()> { + let mut rng = rand::thread_rng(); + let init_days: u64 = rng.gen_range(1..100_00_00); + let mut task_builder = TaskBuilder::default(); + + task_builder.set_frequency_repeated_by_days(init_days); + let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; + + (1..100) + .map(|i| { + debug_assert_eq!( + task.get_next_exec_timestamp().unwrap(), + get_timestamp() + (init_days * (i - 1) * ONE_DAY) + ); + }) + .for_each(drop); + + Ok(()) + } + + #[test] + fn test_count_down() -> AnyResult<()> { + let mut task_builder = TaskBuilder::default(); + + // The third run returns to an invalid state. + task_builder.set_frequency_count_down_by_seconds(1, 3); + let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; + + assert!(task.down_count_and_set_vaild()); + assert!(task.down_count_and_set_vaild()); + assert!(!task.down_count_and_set_vaild()); + + task_builder.set_frequency_count_down_by_cron_str("* * * * * * *", 3); + let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; + + assert!(task.down_count_and_set_vaild()); + assert!(task.down_count_and_set_vaild()); + assert!(!task.down_count_and_set_vaild()); + + task_builder.set_frequency_once_by_seconds(10); + let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; + assert!(!task.down_count_and_set_vaild()); + + task_builder.set_frequency_count_down_by_hours(10, 10); + let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; + (1i32..10i32) + .map(|_| assert!(task.down_count_and_set_vaild())) + .for_each(drop); + assert!(!task.down_count_and_set_vaild()); + Ok(()) } #[test] fn test_is_can_running() -> AnyResult<()> { - use super::{Frequency, Task, TaskBuilder}; - use crate::utils::convenience::functions::create_default_delay_task_handler; let mut task_builder = TaskBuilder::default(); - //The third run returns to an invalid state. - task_builder.set_frequency(Frequency::CountDown(3, "* * * * * * *")); + // The third run returns to an invalid state. + task_builder.set_frequency_count_down_by_cron_str("* * * * * * *", 3); + let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; + + assert!(task.is_can_running()); + + task.set_cylinder_line(1); + assert!(!task.is_can_running()); + + assert!(task.check_arrived()); + + // set_frequency_count_down_by_seconds. + task_builder.set_frequency_count_down_by_seconds(1, 1); let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; assert!(task.is_can_running()); @@ -713,15 +1132,12 @@ mod tests { Ok(()) } - // struct CandyCron - #[test] fn test_candy_cron() -> AnyResult<()> { use super::{CandyCron, CandyFrequency, Task, TaskBuilder}; - use crate::utils::convenience::functions::create_default_delay_task_handler; let mut task_builder = TaskBuilder::default(); - //The third run returns to an invalid state. + // The third run returns to an invalid state. task_builder.set_frequency_by_candy(CandyFrequency::CountDown(5, CandyCron::Minutely)); let mut task: Task = task_builder.spawn(|_context| create_default_delay_task_handler())?; diff --git a/src/timer/timer_core.rs b/src/timer/timer_core.rs index c295ce7..54659f4 100644 --- a/src/timer/timer_core.rs +++ b/src/timer/timer_core.rs @@ -168,7 +168,6 @@ impl Timer { } } - //TODO:cfg macro #[cfg(feature = "status_report")] pub(crate) fn set_status_report_sender(&mut self, sender: AsyncSender) { self.status_report_sender = Some(sender); @@ -215,6 +214,8 @@ impl Timer { } } + trace!("timestamp: {}, task_ids: {:?}", timestamp, task_ids); + for task_id in task_ids { let task_option: Option; @@ -281,9 +282,10 @@ impl Timer { parallel_runnable_num = task_flag_map.value().get_parallel_runnable_num(); } - //if runnable_task.parallel_runnable_num >= task.maximum_parallel_runnable_num doesn't run it. + // if runnable_task.parallel_runnable_num >= task.maximum_parallel_runnable_num doesn't run it. if parallel_runnable_num >= maximum_parallel_runnable_num { + trace!("task-id: {}, parallel_runnable_num >= maximum_parallel_runnable_num doesn't run it", task.task_id); return self.handle_task(task, timestamp, next_second_hand, false); } } @@ -333,8 +335,8 @@ impl Timer { // Time difference + next second hand % DEFAULT_TIMER_SLOT_COUNT let step = task_excute_timestamp.checked_sub(timestamp).unwrap_or(1) + next_second_hand; - let quan = step / DEFAULT_TIMER_SLOT_COUNT; - task.set_cylinder_line(quan); + let cylinder_line = step / DEFAULT_TIMER_SLOT_COUNT; + task.set_cylinder_line(cylinder_line); let slot_seed = step % DEFAULT_TIMER_SLOT_COUNT; { @@ -359,6 +361,11 @@ impl Timer { task_flag_map.value_mut().inc_parallel_runnable_num(); } } + + debug!( + "task-id: {} , next-exec-timestamp: {}, slot-seed: {}, cylinder-line: {}", + task_id, task_excute_timestamp, slot_seed, cylinder_line + ); Ok(()) } } diff --git a/tests/simulation.rs b/tests/simulation.rs index dda823c..34c1b16 100644 --- a/tests/simulation.rs +++ b/tests/simulation.rs @@ -1,3 +1,4 @@ +#![allow(deprecated)] use delay_timer::prelude::*; use std::str::FromStr; @@ -20,7 +21,7 @@ fn test_instance_state() -> anyhow::Result<()> { }); let task = TaskBuilder::default() - .set_frequency_by_candy(CandyFrequency::CountDown(4, CandyCron::Secondly)) + .set_frequency_count_down_by_seconds(1, 4) .set_task_id(1) .set_maximum_parallel_runnable_num(3) .spawn(body)?; @@ -62,7 +63,7 @@ fn test_instance_timeout_state() -> anyhow::Result<()> { }); let task = TaskBuilder::default() - .set_frequency_by_candy(CandyFrequency::CountDown(4, CandyCron::Secondly)) + .set_frequency_count_down_by_seconds(1, 4) .set_task_id(1) .set_maximum_running_time(2) .set_maximum_parallel_runnable_num(3) @@ -174,7 +175,7 @@ fn go_works() -> AnyResult<()> { }; let task = TaskBuilder::default() - .set_frequency(Frequency::CountDown(3, expression)) + .set_frequency_count_down_by_cron_str(expression, 3) .set_task_id(1) .spawn(body)?; delay_timer.add_task(task)?; @@ -204,8 +205,10 @@ fn test_advance() -> AnyResult<()> { create_default_delay_task_handler() }; + // Allow once. + #[allow(deprecated)] let task = TaskBuilder::default() - .set_frequency(Frequency::CountDown(3, expression)) + .set_frequency_count_down_by_cron_str(expression, 3) .set_task_id(task_id) .spawn(body)?; @@ -263,7 +266,7 @@ fn tests_countdown() -> AnyResult<()> { }; let task = TaskBuilder::default() - .set_frequency(Frequency::CountDown(3, "0/2 * * * * * *")) + .set_frequency_count_down_by_seconds(2, 3) .set_task_id(1) .spawn(body)?; delay_timer.add_task(task)?;