Struct clokwerk::AsyncScheduler [−][src]
pub struct AsyncScheduler<Tz = Local, Tp = ChronoTimeProvider> where
Tz: TimeZone,
Tp: TimeProvider, { /* fields omitted */ }
An asynchronous job scheduler, for use with Future
s.
The asynchronous scheduler works almost identically to the synchronous one, except that
instead of taking functions or closures returning ()
, it takes functions or closures returning values implementing Future<Output = ()>
.
Unlike the synchronous version, there is no watch_thread
method, as it would tie
this crate to a specific runtime, and also because it’s trivial to implement by hand. For example, using tokio:
tokio::spawn(async move { loop { scheduler.run_pending().await; tokio::time::sleep(Duration::from_millis(100)).await; } });
For async_std:
async_std::task::spawn(async move { loop { scheduler.run_pending().await; async_std::task::sleep(Duration::from_millis(100)).await; } });
Usage examples
The examples below are intended to demonstrate how to work with various types of Future. See synchronous examples for more examples of how to schedule tasks.
// Scheduler, trait for .seconds(), .minutes(), etc., and trait with job scheduling methods use clokwerk::{AsyncScheduler, TimeUnits, Job}; // Import week days and WeekDay use clokwerk::Interval::*; use std::time::Duration; // Create a new scheduler let mut scheduler = AsyncScheduler::new(); // Add some tasks to it scheduler .every(10.minutes()) .plus(30.seconds()) .run(|| async { println!("Simplest is just using an async block"); }); scheduler .every(1.day()) .at("3:20 pm") .run(|| some_async_fn()); scheduler .every(Wednesday) .at("14:20:17") .run(some_async_fn); scheduler .every(Tuesday) .at("14:20:17") .and_every(Thursday) .at("15:00") .run(|| std::pin::Pin::from(returns_boxed_future())); scheduler .every(Weekday) .run(|| returns_pinned_boxed_future()); scheduler .every(1.day()) .at("3:20 pm") .run(returns_pinned_boxed_future).once(); // Manually run the scheduler forever loop { scheduler.run_pending().await; tokio::time::sleep(Duration::from_millis(10)).await; } // Or spawn a task to run it forever tokio::spawn(async move { loop { scheduler.run_pending().await; tokio::time::sleep(Duration::from_millis(100)).await; } });
Implementations
impl AsyncScheduler
[src]
impl AsyncScheduler
[src]pub fn new() -> Self
[src]
Create a new scheduler. Dates and times will be interpretted using the local timezone
pub fn with_tz<Tz: TimeZone>(tz: Tz) -> AsyncScheduler<Tz>
[src]
Create a new scheduler. Dates and times will be interpretted using the specified timezone.
pub fn with_tz_and_provider<Tz: TimeZone, Tp: TimeProvider>(
tz: Tz
) -> AsyncScheduler<Tz, Tp>
[src]
tz: Tz
) -> AsyncScheduler<Tz, Tp>
Create a new scheduler. Dates and times will be interpretted using the specified timezone. In addition, you can provide an alternate time provider. This is mostly useful for writing tests.
impl<Tz, Tp> AsyncScheduler<Tz, Tp> where
Tz: TimeZone + Sync + Send,
Tp: TimeProvider,
[src]
impl<Tz, Tp> AsyncScheduler<Tz, Tp> where
Tz: TimeZone + Sync + Send,
Tp: TimeProvider,
[src]pub fn every(&mut self, ival: Interval) -> &mut AsyncJob<Tz, Tp>
[src]
Add a new job to the scheduler to be run on the given interval
let mut scheduler = AsyncScheduler::new(); scheduler.every(10.minutes()).plus(30.seconds()).run(|| async { println!("Periodic task") }); scheduler.every(1.day()).at("3:20 pm").run(|| some_async_fn()); scheduler.every(Wednesday).at("14:20:17").run(|| Pin::from(returns_boxed_future())); scheduler.every(Weekday).run(|| returns_pinned_boxed_future());
pub fn run_pending(&mut self) -> AsyncSchedulerFuture
[src]
Run all jobs that should run at this time.
This method returns a future that will poll each of the tasks until they are completed.
use std::time::Duration; loop { scheduler.run_pending().await; tokio::time::sleep(Duration::from_millis(100)).await; }
Note that while all pending jobs will run asynchronously, a long-running task can still
block future executions if you await
the future returned by this method.
If you are concerned that a task might run for a long time, there are several possible approaches:
- Pass the result of
scheduler.run_pending()
to your runtime’sspawn
function. This might result in multiple invocations of the same task running concurrently. - Use
spawn
orspawn_blocking
in your task itself. This has the same concurrent execution risk as approach 1, but limited to that specific task. - Use
tokio::time::timeout
or equivalent to preventscheduler.run_pending()
or the task itself from running more than an expected amount of time. E.g.
use std::time::Duration; let mut scheduler = AsyncScheduler::new(); scheduler.every(10.minutes()).run(|| async { if let Err(_) = tokio::time::timeout(Duration::from_secs(10 * 60), scrape_pages()).await { eprintln!("Timed out scraping pages") } });
Trait Implementations
impl<Tz: Debug, Tp: Debug> Debug for AsyncScheduler<Tz, Tp> where
Tz: TimeZone,
Tp: TimeProvider,
[src]
impl<Tz: Debug, Tp: Debug> Debug for AsyncScheduler<Tz, Tp> where
Tz: TimeZone,
Tp: TimeProvider,
[src]impl Default for AsyncScheduler
[src]
impl Default for AsyncScheduler
[src]fn default() -> AsyncScheduler
[src]
Auto Trait Implementations
impl<Tz = Local, Tp = ChronoTimeProvider> !RefUnwindSafe for AsyncScheduler<Tz, Tp>
impl<Tz = Local, Tp = ChronoTimeProvider> !RefUnwindSafe for AsyncScheduler<Tz, Tp>
impl<Tz, Tp> Send for AsyncScheduler<Tz, Tp> where
Tp: Send,
Tz: Send,
<Tz as TimeZone>::Offset: Send,
impl<Tz, Tp> Send for AsyncScheduler<Tz, Tp> where
Tp: Send,
Tz: Send,
<Tz as TimeZone>::Offset: Send,
impl<Tz = Local, Tp = ChronoTimeProvider> !Sync for AsyncScheduler<Tz, Tp>
impl<Tz = Local, Tp = ChronoTimeProvider> !Sync for AsyncScheduler<Tz, Tp>
impl<Tz, Tp> Unpin for AsyncScheduler<Tz, Tp> where
Tp: Unpin,
Tz: Unpin,
<Tz as TimeZone>::Offset: Unpin,
impl<Tz, Tp> Unpin for AsyncScheduler<Tz, Tp> where
Tp: Unpin,
Tz: Unpin,
<Tz as TimeZone>::Offset: Unpin,
impl<Tz = Local, Tp = ChronoTimeProvider> !UnwindSafe for AsyncScheduler<Tz, Tp>
impl<Tz = Local, Tp = ChronoTimeProvider> !UnwindSafe for AsyncScheduler<Tz, Tp>