1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
//! DelayTimer like crontab is a cyclic task manager with latency properties,
//! but synchronous asynchronous tasks are possible,
//! based on an internal event manager and task scheduler,
//! and supported by the runtime provided by smol and tokio,
//! which makes it easy to manage and dynamic add/cancel/remove is supported.
//!
//! - [TaskBuilder](crate::timer::task::TaskBuilder) It is a builder for [Task](crate::timer::task::Task)
//!   that provides APIs for setting such as maximum number of parallel runs,
//!   run content, run identity, run duration, etc.
//! - [DelayTimerBuilder](crate::entity::DelayTimerBuilder) It is a builder for
//!   [DelayTimer](crate::entity::DelayTimer) that provides APIs for setting such as customization runtime
//!   and enable status-report.
//!
//!
//!
//! # Usage
//!
//! First, add this to your Cargo.toml
//!
//! ```toml
//! [dependencies]
//! delay_timer = "*"
//! ```
//!
//! Next:
//!
//! ``` rust
//!
//! use anyhow::Result;
//! use delay_timer::prelude::*;
//! use std::time::Duration;
//! use smol::Timer;
//!
//! fn main() -> Result<()> {
//!     // Build an DelayTimer that uses the default configuration of the `smol` runtime internally.
//!     let delay_timer = DelayTimerBuilder::default().build();
//!
//!     // Develop a print job that runs in an asynchronous cycle.
//!     // A chain of task instances.
//!     let task_instance_chain = delay_timer.insert_task(build_task_async_print())?;
//!
//!     // Get the running instance of task 1.
//!     let task_instance = task_instance_chain.next_with_wait()?;
//!
//!     // Cancel running task instances.
//!     task_instance.cancel_with_wait()?;
//!
//!     // Remove task which id is 1.
//!     delay_timer.remove_task(1)?;
//!
//!     // No new tasks are accepted; running tasks are not affected.
//!     delay_timer.stop_delay_timer()?;
//!
//!     Ok(())
//! }
//!
//! fn build_task_async_print() -> Result<Task, TaskError> {
//!     let mut task_builder = TaskBuilder::default();
//!
//!     let body = create_async_fn_body!({
//!         println!("create_async_fn_body!");
//!
//!         Timer::after(Duration::from_secs(3)).await;
//!
//!         println!("create_async_fn_body:i'success");
//!     });
//!
//!     task_builder
//!         .set_task_id(1)
//!         .set_frequency_by_candy(CandyFrequency::Repeated(CandyCron::Secondly))
//!         .set_maximun_parallel_runable_num(2)
//!         .spawn(body)
//! }
//!
//! ```
//!
//!
//! Use in asynchronous contexts.
//! ```
//!
//! use delay_timer::prelude::*;
//!
//! use anyhow::Result;
//!
//! use smol::Timer;
//! use std::time::Duration;
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//!     // In addition to the mixed (smol & tokio) runtime
//!     // You can also share a tokio runtime with delayTimer, please see api `DelayTimerBuilder::tokio_runtime` for details.
//!
//!     // Build an DelayTimer that uses the default configuration of the Smol runtime internally.
//!     let delay_timer = DelayTimerBuilder::default().build();
//!
//!     // Develop a print job that runs in an asynchronous cycle.
//!     let task_instance_chain = delay_timer.insert_task(build_task_async_print())?;
//!
//!     // Get the running instance of task 1.
//!     let task_instance = task_instance_chain.next_with_async_wait().await?;
//!
//!     // Cancel running task instances.
//!     task_instance.cancel_with_async_wait().await?;
//!
//!
//!     // Remove task which id is 1.
//!     delay_timer.remove_task(1)?;
//!
//!     // No new tasks are accepted; running tasks are not affected.
//!     delay_timer.stop_delay_timer()
//! }
//!
//! fn build_task_async_print() -> Result<Task, TaskError> {
//!     let mut task_builder = TaskBuilder::default();
//!
//!     let body = create_async_fn_body!({
//!         println!("create_async_fn_body!");
//!
//!         Timer::after(Duration::from_secs(3)).await;
//!
//!         println!("create_async_fn_body:i'success");
//!     });
//!
//!     task_builder
//!         .set_task_id(1)
//!         .set_frequency(Frequency::Repeated("*/6 * * * * * *"))
//!         .set_maximun_parallel_runable_num(2)
//!         .spawn(body)
//! }
//!
//!
//!
//!
//! ```
//! Capture the specified environment information and build the closure & task:
//! ```
//! #[macro_use]
//! use delay_timer::prelude::*;
//!
//! use std::sync::atomic::{
//!     AtomicUsize,
//!     Ordering::{Acquire, Release},
//! };
//! use std::sync::Arc;
//! use std::time::Duration;
//! use smol::Timer;
//!
//!
//! 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)?;
//!
//! delay_timer.add_task(task).ok();
//!
//! ```
//!
//!
//!
//! Building dynamic future tasks:
//  TODO: We cannot set the `required-features` of toml-tag on a document test.
//  Wating for `https://doc.rust-lang.org/rustdoc/documentation-tests.html` update.
//! ```
//! #[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) -> Result<Task, TaskError> {
//!     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)
//! }
//!
//! 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(None).await;
//!         };
//!
//!         create_delay_task_handler(async_spawn(future))
//!     }
//! }
//!
//! pub async fn async_template(id: i32, name: String) -> AnyResult<()> {
//!     let client = Client::new();
//!
//!     let url = format!("http://httpbin.org/get?id={}&name={}", id, name);
//!     let uri: Uri = url.parse()?;
//!     let res = client.get(uri).await?;
//!     println!("Response: {}", res.status());
//!     // Concatenate the body stream into a single buffer...
//!     let buf = hyper::body::to_bytes(res).await?;
//!     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()),
//!         }
//!     }
//! }
//! ```
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
#![cfg_attr(RUSTC_IS_NIGHTLY, feature(linked_list_cursors))]
#![cfg_attr(docsrs, feature(doc_cfg))]
#[macro_use]
pub mod macros;
pub mod entity;
pub mod error;
pub mod prelude;
pub mod timer;
pub mod utils;

pub use anyhow;
pub use cron_clock;
pub use snowflake;