diff --git a/Cargo.toml b/Cargo.toml index b687b62..d19cfcb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "skedge" description = "Ergonomic single-process job scheduling for Rust programs." -version = "0.0.6" +version = "0.1.0" edition = "2018" authors = ["Ben Lovy "] documentation = "https://docs.rs/skedge" diff --git a/README.md b/README.md index 4caa529..1bf6b35 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,10 @@ [![Crates.io](https://img.shields.io/crates/v/skedge.svg)](https://crates.io/crates/skedge) [![rust action](https://github.com/deciduously/skedge/actions/workflows/rust.yml/badge.svg)](https://github.com/deciduously/skedge/actions/workflows/rust.yml) -[![docs.rs](https://img.shields.io/docsrs/skedge)](https://docs.rs/skedge/) +[![docs.rs](https://img.shields.io/docsrs/skedge/0.1.0)](https://docs.rs/skedge/0.1.0) Rust single-process scheduling. Ported from [`schedule`](https://github.com/dbader/schedule) for Python, in turn inspired by [`clockwork`](https://github.com/Rykian/clockwork) (Ruby), and ["Rethinking Cron"](https://adam.herokuapp.com/past/2010/4/13/rethinking_cron/) by [Adam Wiggins](https://github.com/adamwiggins). -**NOTE**: This library is currently limited to jobs which take no arguments and return nothing. - ## Usage Documentation can be found on [docs.rs](https://docs.rs/skedge). @@ -16,30 +14,22 @@ This library uses the Builder pattern to define jobs. Instantiate a fresh `Sche ```rust use chrono::Local; -use skedge::{every, every_single, Scheduler}; +use skedge::{every, Scheduler}; use std::thread::sleep; use std::time::Duration; -fn job() { - println!("Hello, it's {}!", Local::now()); +fn greet(name: &str) { + println!("Hello {}, it's {}!", name, Local::now().to_rfc2822()); } fn main() -> Result<(), Box> { let mut schedule = Scheduler::new(); - every(10).seconds()?.run(&mut schedule, job)?; - every(10).minutes()?.run(&mut schedule, job)?; - every_single().hour()?.run(&mut schedule, job)?; - every_single().day()?.at("10:30")?.run(&mut schedule, job); - every(5).to(10)?.minutes()?.run(&mut schedule, job); - every_single().monday()?.run(&mut schedule, job); - every_single().wednesday()?.at("13:15")?.run(&mut schedule, job); - every_single().minute()?.at(":17")?.run(&mut schedule, job); every(2) .to(8)? .seconds()? .until(Local::now() + chrono::Duration::seconds(30))? - .run(&mut schedule, job)?; + .run_one_arg(&mut schedule, greet, "Good-Looking")?; println!("Starting at {}", Local::now()); loop { @@ -51,7 +41,7 @@ fn main() -> Result<(), Box> { } ``` -Try `cargo run --example basic` to see it in action. +Check out the [example script](https://github.com/deciduously/skedge/blob/main/examples/basic.rs) to see more configuration options. Try `cargo run --example readme` or `cargo run --example basic` to see it in action. ## Development @@ -73,5 +63,4 @@ Clone this repo. See [`CONTRIBUTING.md`](https://github.com/deciduously/skedge/ #### Development-Only - * [mockall](https://github.com/asomers/mockall) - Mock objects * [pretty_assertions](https://github.com/colin-kiegel/rust-pretty-assertions) - Colorful assertion output \ No newline at end of file diff --git a/examples/basic.rs b/examples/basic.rs index c48de15..d4b10b2 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -1,32 +1,59 @@ +// Some more varied usage examples. + use chrono::Local; use skedge::{every, every_single, Scheduler}; use std::thread::sleep; use std::time::Duration; fn job() { - println!("Hello, it's {}!", Local::now()); + println!("Hello, it's {}!", Local::now().to_rfc2822()); +} + +fn flirt(name: &str, time: &str, hour: u8, jackpot: f32, restaurant: &str, meal: &str) { + println!( + "Hello, {}! What are you doing {}? I'm free around {}. \ + I just won ${:.*} off a scratch ticket, you can get anything you want. \ + Have you ever been to {}? They're getting rave reviews over their {}.", + name, time, hour, 2, jackpot, restaurant, meal + ); } fn main() -> Result<(), Box> { let mut schedule = Scheduler::new(); every(10).seconds()?.run(&mut schedule, job)?; + every(10).minutes()?.run(&mut schedule, job)?; + every_single().hour()?.run(&mut schedule, job)?; + every_single().day()?.at("10:30")?.run(&mut schedule, job)?; + every(5).to(10)?.minutes()?.run(&mut schedule, job)?; + every_single().monday()?.run(&mut schedule, job)?; + every_single() .wednesday()? .at("13:15")? .run(&mut schedule, job)?; + every(2) .to(8)? .seconds()? - .until(Local::now() + chrono::Duration::seconds(30))? - .run(&mut schedule, job)?; + .until(Local::now() + chrono::Duration::days(5))? + .run_six_args( + &mut schedule, + flirt, + "Good-Looking", + "Friday", + 7, + 40., + "Dorsia", + "foraged chanterelle croque monsieur", + )?; - println!("Starting at {}", Local::now()); + println!("Starting at {}", Local::now().to_rfc3339()); loop { if let Err(e) = schedule.run_pending() { eprintln!("Error: {}", e); diff --git a/examples/readme.rs b/examples/readme.rs new file mode 100644 index 0000000..e17b5c2 --- /dev/null +++ b/examples/readme.rs @@ -0,0 +1,28 @@ +// This is the exact code from the README.md example + +use chrono::Local; +use skedge::{every, Scheduler}; +use std::thread::sleep; +use std::time::Duration; + +fn greet(name: &str) { + println!("Hello {}, it's {}!", name, Local::now().to_rfc2822()); +} + +fn main() -> Result<(), Box> { + let mut schedule = Scheduler::new(); + + every(2) + .to(8)? + .seconds()? + .until(Local::now() + chrono::Duration::seconds(30))? + .run_one_arg(&mut schedule, greet, "Good-Looking")?; + + println!("Starting at {}", Local::now()); + loop { + if let Err(e) = schedule.run_pending() { + eprintln!("Error: {}", e); + } + sleep(Duration::from_secs(1)); + } +} diff --git a/src/callable.rs b/src/callable.rs index c597500..a609512 100644 --- a/src/callable.rs +++ b/src/callable.rs @@ -3,13 +3,19 @@ use std::fmt; /// A job is anything that implements this trait -pub(crate) trait Callable: fmt::Debug { +pub(crate) trait Callable { /// Execute this callable fn call(&self) -> Option; /// Get the name of this callable fn name(&self) -> &str; } +impl fmt::Debug for dyn Callable { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Callable(name={})", self.name()) + } +} + impl PartialEq for dyn Callable { fn eq(&self, other: &Self) -> bool { // Callable objects are equal if their names are equal @@ -45,3 +51,346 @@ impl Callable for UnitToUnit { &self.name } } + +/// A named callable function taking one parameter and returning nothing. +#[derive(Debug)] +pub struct OneToUnit +where + T: Clone, +{ + name: String, + work: fn(T) -> (), + arg: T, +} + +impl OneToUnit +where + T: Clone, +{ + pub fn new(name: &str, work: fn(T) -> (), arg: T) -> Self { + Self { + name: name.into(), + work, + arg, + } + } +} + +impl Callable for OneToUnit +where + T: Clone, +{ + fn call(&self) -> Option { + (self.work)(self.arg.clone()); + None + } + fn name(&self) -> &str { + &self.name + } +} + +/// A named callable function taking two parameters and returning nothing. +#[derive(Debug)] +pub struct TwoToUnit +where + T: Clone, + U: Clone, +{ + name: String, + work: fn(T, U) -> (), + arg_one: T, + arg_two: U, +} + +impl TwoToUnit +where + T: Clone, + U: Clone, +{ + pub fn new(name: &str, work: fn(T, U) -> (), arg_one: T, arg_two: U) -> Self { + Self { + name: name.into(), + work, + arg_one, + arg_two, + } + } +} + +impl Callable for TwoToUnit +where + T: Clone, + U: Clone, +{ + fn call(&self) -> Option { + (self.work)(self.arg_one.clone(), self.arg_two.clone()); + None + } + fn name(&self) -> &str { + &self.name + } +} + +/// A named callable function taking three parameters and returning nothing. +#[derive(Debug)] +pub struct ThreeToUnit +where + T: Clone, + U: Clone, + V: Clone, +{ + name: String, + work: fn(T, U, V) -> (), + arg_one: T, + arg_two: U, + arg_three: V, +} + +impl ThreeToUnit +where + T: Clone, + U: Clone, + V: Clone, +{ + pub fn new(name: &str, work: fn(T, U, V) -> (), arg_one: T, arg_two: U, arg_three: V) -> Self { + Self { + name: name.into(), + work, + arg_one, + arg_two, + arg_three, + } + } +} + +impl Callable for ThreeToUnit +where + T: Clone, + U: Clone, + V: Clone, +{ + fn call(&self) -> Option { + (self.work)( + self.arg_one.clone(), + self.arg_two.clone(), + self.arg_three.clone(), + ); + None + } + fn name(&self) -> &str { + &self.name + } +} + +/// A named callable function taking three parameters and returning nothing. +#[derive(Debug)] +pub struct FourToUnit +where + T: Clone, + U: Clone, + V: Clone, + W: Clone, +{ + name: String, + work: fn(T, U, V, W) -> (), + arg_one: T, + arg_two: U, + arg_three: V, + arg_four: W, +} + +impl FourToUnit +where + T: Clone, + U: Clone, + V: Clone, + W: Clone, +{ + pub fn new( + name: &str, + work: fn(T, U, V, W) -> (), + arg_one: T, + arg_two: U, + arg_three: V, + arg_four: W, + ) -> Self { + Self { + name: name.into(), + work, + arg_one, + arg_two, + arg_three, + arg_four, + } + } +} + +impl Callable for FourToUnit +where + T: Clone, + U: Clone, + V: Clone, + W: Clone, +{ + fn call(&self) -> Option { + (self.work)( + self.arg_one.clone(), + self.arg_two.clone(), + self.arg_three.clone(), + self.arg_four.clone(), + ); + None + } + fn name(&self) -> &str { + &self.name + } +} + +/// A named callable function taking three parameters and returning nothing. +#[derive(Debug)] +pub struct FiveToUnit +where + T: Clone, + U: Clone, + V: Clone, + W: Clone, + X: Clone, +{ + name: String, + work: fn(T, U, V, W, X) -> (), + arg_one: T, + arg_two: U, + arg_three: V, + arg_four: W, + arg_five: X, +} + +impl FiveToUnit +where + T: Clone, + U: Clone, + V: Clone, + W: Clone, + X: Clone, +{ + pub fn new( + name: &str, + work: fn(T, U, V, W, X) -> (), + arg_one: T, + arg_two: U, + arg_three: V, + arg_four: W, + arg_five: X, + ) -> Self { + Self { + name: name.into(), + work, + arg_one, + arg_two, + arg_three, + arg_four, + arg_five, + } + } +} + +impl Callable for FiveToUnit +where + T: Clone, + U: Clone, + V: Clone, + W: Clone, + X: Clone, +{ + fn call(&self) -> Option { + (self.work)( + self.arg_one.clone(), + self.arg_two.clone(), + self.arg_three.clone(), + self.arg_four.clone(), + self.arg_five.clone(), + ); + None + } + fn name(&self) -> &str { + &self.name + } +} + +/// A named callable function taking three parameters and returning nothing. +#[derive(Debug)] +pub struct SixToUnit +where + T: Clone, + U: Clone, + V: Clone, + W: Clone, + X: Clone, + Y: Clone, +{ + name: String, + work: fn(T, U, V, W, X, Y) -> (), + arg_one: T, + arg_two: U, + arg_three: V, + arg_four: W, + arg_five: X, + arg_six: Y, +} + +impl SixToUnit +where + T: Clone, + U: Clone, + V: Clone, + W: Clone, + X: Clone, + Y: Clone, +{ + pub fn new( + name: &str, + work: fn(T, U, V, W, X, Y) -> (), + arg_one: T, + arg_two: U, + arg_three: V, + arg_four: W, + arg_five: X, + arg_six: Y, + ) -> Self { + Self { + name: name.into(), + work, + arg_one, + arg_two, + arg_three, + arg_four, + arg_five, + arg_six, + } + } +} + +impl Callable for SixToUnit +where + T: Clone, + U: Clone, + V: Clone, + W: Clone, + X: Clone, + Y: Clone, +{ + fn call(&self) -> Option { + (self.work)( + self.arg_one.clone(), + self.arg_two.clone(), + self.arg_three.clone(), + self.arg_four.clone(), + self.arg_five.clone(), + self.arg_six.clone(), + ); + None + } + fn name(&self) -> &str { + &self.name + } +} diff --git a/src/error.rs b/src/error.rs index 289c35e..e7ffd60 100644 --- a/src/error.rs +++ b/src/error.rs @@ -59,4 +59,4 @@ pub(crate) fn weekday_collision_error(intended: Weekday, existing: Weekday) -> S SkedgeError::WeekdayCollision(intended, existing) } -pub(crate) type Result = std::result::Result; +pub type Result = std::result::Result; diff --git a/src/job.rs b/src/job.rs index 39e176e..ef945b8 100644 --- a/src/job.rs +++ b/src/job.rs @@ -12,9 +12,7 @@ use std::{ fmt, }; -use crate::{ - error::*, time::RealTime, Callable, Scheduler, TimeUnit, Timekeeper, Timestamp, UnitToUnit, -}; +use crate::*; /// A Tag is used to categorize a job. pub type Tag = String; @@ -149,6 +147,20 @@ impl Job { /// * Minute jobs: `:SS` /// /// Not supported on weekly, monthly, or yearly jobs. + /// + /// ```rust + /// # use skedge::*; + /// # fn job() {} + /// # fn main() -> Result<()> { + /// # let mut scheduler = Scheduler::new(); + /// every(3).minutes()?.at(":15")?.run(&mut scheduler, job)?; + /// every_single().hour()?.at(":30")?.run(&mut scheduler, job)?; + /// every(12).hours()?.at("08:45")?.run(&mut scheduler, job)?; + /// every_single().wednesday()?.at("13:30")?.run(&mut scheduler, job)?; + /// every(10).days()?.at("00:00:12")?.run(&mut scheduler, job)?; + /// # Ok(()) + /// # } + /// ``` pub fn at(mut self, time_str: &str) -> Result { use TimeUnit::*; @@ -184,11 +196,15 @@ impl Job { } else if num_vals == 2 && self.unit == Some(Minute) { second = time_vals[1].parse().unwrap(); } else if num_vals == 2 && self.unit == Some(Hour) { - minute = time_vals[0].parse().unwrap(); + minute = if time_vals[0].len() > 0 { + time_vals[0].parse().unwrap() + } else { + 0 + }; second = time_vals[1].parse().unwrap(); } else { hour = time_vals[0].parse().unwrap(); - minute = time_vals[0].parse().unwrap(); + minute = time_vals[1].parse().unwrap(); } if self.unit == Some(Day) || self.start_day.is_some() { @@ -207,9 +223,17 @@ impl Job { Ok(self) } - /// Schedule the job to run at a regular randomized interval. + /// Schedule the job to run at a randomized interval between two extremes. /// - /// E.g. every(3).to(6).seconds + /// ```rust + /// # use skedge::*; + /// # fn job() {} + /// # fn main() -> Result<()> { + /// # let mut scheduler = Scheduler::new(); + /// every(3).to(6)?.seconds()?.run(&mut scheduler, job)?; + /// # Ok(()) + /// # } + /// ``` pub fn to(mut self, latest: Interval) -> Result { if latest <= self.interval { Err(SkedgeError::InvalidInterval) @@ -227,7 +251,17 @@ impl Job { /// the job was scheduled to run before until_time, but runs after until_time. /// If until_time is a moment in the past, returns an error. /// - /// + /// ```rust + /// # use skedge::*; + /// # fn job() {} + /// # fn main() -> Result<()> { + /// # let mut scheduler = Scheduler::new(); + /// use chrono::Duration; + /// let deadline = chrono::Local::now() + Duration::minutes(10); + /// every_single().minute()?.at(":15")?.until(deadline)?.run(&mut scheduler, job)?; + /// # Ok(()) + /// # } + /// ``` pub fn until(mut self, until_time: Timestamp) -> Result { if until_time < self.now() { return Err(SkedgeError::InvalidUntilTime); @@ -237,14 +271,301 @@ impl Job { } /// Specify the work function that will execute when this job runs and add it to the schedule + /// + /// ```rust + /// # use skedge::*; + /// fn job() { + /// println!("Hello!"); + /// } + /// # fn main() -> Result<()> { + /// # let mut scheduler = Scheduler::new(); + /// + /// every(10).seconds()?.run(&mut scheduler, job)?; + /// # Ok(()) + /// # } + /// ``` pub fn run(mut self, scheduler: &mut Scheduler, job: fn() -> ()) -> Result<()> { - // FIXME how does job naming work? without reflection? self.job = Some(Box::new(UnitToUnit::new("job", job))); self.schedule_next_run()?; scheduler.add_job(self); Ok(()) } + /// Specify the work function with one argument that will execute when this job runs and add it to the schedule + /// + /// ```rust + /// # use skedge::*; + /// fn job(name: &str) { + /// println!("Hello, {}!", name); + /// } + /// # fn main() -> Result<()> { + /// # let mut scheduler = Scheduler::new(); + /// + /// every(10) + /// .seconds()? + /// .run_one_arg(&mut scheduler, job, "Good-Looking")?; + /// # Ok(()) + /// # } + /// ``` + pub fn run_one_arg( + mut self, + scheduler: &mut Scheduler, + job: fn(T) -> (), + arg: T, + ) -> Result<()> + where + T: 'static + Clone, + { + self.job = Some(Box::new(OneToUnit::new("job_one_arg", job, arg))); + self.schedule_next_run()?; + scheduler.add_job(self); + Ok(()) + } + + /// Specify the work function with two arguments that will execute when this job runs and add it to the schedule + /// ```rust + /// # use skedge::*; + /// fn job(name: &str, time: &str) { + /// println!("Hello, {}! What are you doing {}?", name, time); + /// } + /// # fn main() -> Result<()> { + /// # let mut scheduler = Scheduler::new(); + /// + /// every(10) + /// .seconds()? + /// .run_two_args(&mut scheduler, job, "Good-Looking", "this weekend")?; + /// # Ok(()) + /// # } + /// ``` + pub fn run_two_args( + mut self, + scheduler: &mut Scheduler, + job: fn(T, U) -> (), + arg_one: T, + arg_two: U, + ) -> Result<()> + where + T: 'static + Clone, + U: 'static + Clone, + { + self.job = Some(Box::new(TwoToUnit::new( + "job_two_args", + job, + arg_one, + arg_two, + ))); + self.schedule_next_run()?; + scheduler.add_job(self); + Ok(()) + } + + /// Specify the work function with three arguments that will execute when this job runs and add it to the schedule + /// ```rust + /// # use skedge::*; + /// fn job(name: &str, time: &str, hour: u8) { + /// println!( + /// "Hello, {}! What are you doing {}? I'm free around {}.", + /// name, time, hour + /// ); + /// } + /// # fn main() -> Result<()> { + /// # let mut scheduler = Scheduler::new(); + /// + /// every(10) + /// .seconds()? + /// .run_three_args(&mut scheduler, job, "Good-Looking", "Friday", 7)?; + /// # Ok(()) + /// # } + /// ``` + pub fn run_three_args( + mut self, + scheduler: &mut Scheduler, + job: fn(T, U, V) -> (), + arg_one: T, + arg_two: U, + arg_three: V, + ) -> Result<()> + where + T: 'static + Clone, + U: 'static + Clone, + V: 'static + Clone, + { + self.job = Some(Box::new(ThreeToUnit::new( + "job_three_args", + job, + arg_one, + arg_two, + arg_three, + ))); + self.schedule_next_run()?; + scheduler.add_job(self); + Ok(()) + } + + /// Specify the work function with four arguments that will execute when this job runs and add it to the schedule + /// ```rust + /// # use skedge::*; + /// fn job(name: &str, time: &str, hour: u8, jackpot: f32) { + /// println!( + /// "Hello, {}! What are you doing {}? I'm free around {}. \ + /// I just won ${:.*} off a scratch ticket, you can get anything you want.", + /// name, time, hour, 2, jackpot + /// ); + /// } + /// + /// # fn main() -> Result<()> { + /// # let mut scheduler = Scheduler::new(); + /// + /// every(10) + /// .seconds()? + /// .run_four_args(&mut scheduler, job, "Good-Looking", "Friday", 7, 40.)?; + /// # Ok(()) + /// # } + /// ``` + pub fn run_four_args( + mut self, + scheduler: &mut Scheduler, + job: fn(T, U, V, W) -> (), + arg_one: T, + arg_two: U, + arg_three: V, + arg_four: W, + ) -> Result<()> + where + T: 'static + Clone, + U: 'static + Clone, + V: 'static + Clone, + W: 'static + Clone, + { + self.job = Some(Box::new(FourToUnit::new( + "job_four_args", + job, + arg_one, + arg_two, + arg_three, + arg_four, + ))); + self.schedule_next_run()?; + scheduler.add_job(self); + Ok(()) + } + + /// Specify the work function with five arguments that will execute when this job runs and add it to the schedule + /// ```rust + /// # use skedge::*; + /// fn job(name: &str, time: &str, hour: u8, jackpot: f32, restaurant: &str) { + /// println!( + /// "Hello, {}! What are you doing {}? I'm free around {}. \ + /// I just won ${:.*} off a scratch ticket, you can get anything you want. \ + /// Have you ever been to {}? It's getting rave reviews.", + /// name, time, hour, 2, jackpot, restaurant + /// ); + /// } + /// + /// # fn main() -> Result<()> { + /// # let mut scheduler = Scheduler::new(); + /// + /// every(10) + /// .seconds()? + /// .run_five_args(&mut scheduler, job, "Good-Looking", "Friday", 7, 40., "Dorsia")?; + /// # Ok(()) + /// # } + /// ``` + pub fn run_five_args( + mut self, + scheduler: &mut Scheduler, + job: fn(T, U, V, W, X) -> (), + arg_one: T, + arg_two: U, + arg_three: V, + arg_four: W, + arg_five: X, + ) -> Result<()> + where + T: 'static + Clone, + U: 'static + Clone, + V: 'static + Clone, + W: 'static + Clone, + X: 'static + Clone, + { + self.job = Some(Box::new(FiveToUnit::new( + "job_four_args", + job, + arg_one, + arg_two, + arg_three, + arg_four, + arg_five, + ))); + self.schedule_next_run()?; + scheduler.add_job(self); + Ok(()) + } + + /// Specify the work function with six arguments that will execute when this job runs and add it to the schedule + /// ```rust + /// # use skedge::*; + /// fn job(name: &str, time: &str, hour: u8, jackpot: f32, restaurant: &str, meal: &str) { + /// println!( + /// "Hello, {}! What are you doing {}? I'm free around {}. \ + /// I just won ${:.*} off a scratch ticket, you can get anything you want. \ + /// Have you ever been to {}? They're getting rave reviews over their {}.", + /// name, time, hour, 2, jackpot, restaurant, meal + /// ); + /// } + /// + /// # fn main() -> Result<()> { + /// # let mut scheduler = Scheduler::new(); + /// + /// every(10) + /// .seconds()? + /// .run_six_args( + /// &mut scheduler, + /// job, + /// "Good-Looking", + /// "Friday", + /// 7, + /// 40., + /// "Dorsia", + /// "foraged chanterelle croque monsieur", + /// )?; + /// # Ok(()) + /// # } + /// ``` + pub fn run_six_args( + mut self, + scheduler: &mut Scheduler, + job: fn(T, U, V, W, X, Y) -> (), + arg_one: T, + arg_two: U, + arg_three: V, + arg_four: W, + arg_five: X, + arg_six: Y, + ) -> Result<()> + where + T: 'static + Clone, + U: 'static + Clone, + V: 'static + Clone, + W: 'static + Clone, + X: 'static + Clone, + Y: 'static + Clone, + { + self.job = Some(Box::new(SixToUnit::new( + "job_four_args", + job, + arg_one, + arg_two, + arg_three, + arg_four, + arg_five, + arg_six, + ))); + self.schedule_next_run()?; + scheduler.add_job(self); + Ok(()) + } + /// Check whether this job should be run now pub fn should_run(&self) -> bool { self.next_run.is_some() && self.now() >= self.next_run.unwrap() diff --git a/src/lib.rs b/src/lib.rs index d917127..550bd72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,10 +2,16 @@ //! //! `skedge` is a single-process job scheduler. //! -//! Define a work function. Currently, this is restricted to functions which take no arguments and return nothing: +//! Define a work function: //! ```rust //! fn job() { -//! println!("Hello, it's {}!", chrono::Local::now()); +//! println!("Hello, it's {}!", chrono::Local::now().to_rfc2822()); +//! } +//! ``` +//! You can use up to six arguments: +//! ```rust +//! fn greet(name: &str) { +//! println!("Hello, {}!", name); //! } //! ``` //! Instantiate a `Scheduler` and schedule jobs: @@ -17,6 +23,9 @@ //! # fn job() { //! # println!("Hello, it's {}!", Local::now()); //! # } +//! # fn greet(name: &str) { +//! # println!("Hello, {}!", name); +//! # } //! # fn main() -> Result<(), Box> { //! let mut schedule = Scheduler::new(); //! @@ -29,13 +38,14 @@ //! every_single().wednesday()?.at("13:15")?.run(&mut schedule, job)?; //! every_single().minute()?.at(":17")?.run(&mut schedule, job)?; //! every(2) -//! .to(8)? -//! .seconds()? -//! .until(Local::now() + chrono::Duration::seconds(30))? -//! .run(&mut schedule, job)?; +//! .to(8)? +//! .seconds()? +//! .until(Local::now() + chrono::Duration::seconds(30))? +//! .run_one_arg(&mut schedule, greet, "Good-Looking")?; //! # Ok(()) //! # } //! ``` +//! Note that you must use the appropriate run_x_args() method for job functions taking multiple arguments. //! In your main loop, you can use `Scheduler::run_pending()` to fire all scheduled jobs at the proper time: //! ```no_run //! # use skedge::Scheduler; @@ -54,7 +64,8 @@ mod job; mod scheduler; mod time; -use callable::{Callable, UnitToUnit}; +use callable::*; +pub use error::*; pub use job::{every, every_single, Interval, Job, Tag}; pub use scheduler::Scheduler; -use time::{TimeUnit, Timekeeper, Timestamp}; +use time::{RealTime, TimeUnit, Timekeeper, Timestamp}; diff --git a/src/scheduler.rs b/src/scheduler.rs index 59d1967..a8d46b4 100644 --- a/src/scheduler.rs +++ b/src/scheduler.rs @@ -1,6 +1,6 @@ //! The scheduler is responsible for managing all scheduled jobs. -use crate::{error::*, Job, Tag, Timekeeper, Timestamp}; +use crate::{Job, Result, Tag, Timekeeper, Timestamp}; use log::*; /// A Scheduler creates jobs, tracks recorded jobs, and executes jobs.