uhrwerk 0.1.0

Simple scheduler for recurring tasks
Documentation
use crate::{
	Interval,
	job::Job,
	job_schedule::{JobSchedule, WithSchedule},
	timeprovider::{DefaultTimeProvider, TimeProvider}
};
use std::fmt::{self, Debug, Formatter};
use time::{OffsetDateTime, UtcOffset};

/// A job to run on the scheduler.
/// Create these by calling [`Scheduler::every()`](crate::Scheduler::every).
///
/// Methods for scheduling the job live in the [Job] trait.
pub struct SyncJob<TP = DefaultTimeProvider> {
	schedule: JobSchedule<TP>,
	job: Option<Box<dyn FnMut() + Send>>
}

impl<TP: TimeProvider> WithSchedule<TP> for SyncJob<TP> {
	fn schedule_mut(&mut self) -> &mut JobSchedule<TP> {
		&mut self.schedule
	}

	fn schedule(&self) -> &JobSchedule<TP> {
		&self.schedule
	}
}

impl<TP> Debug for SyncJob<TP> {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		self.schedule.fmt(f)
	}
}

impl<TP> Job<TP> for SyncJob<TP> where TP: TimeProvider {}

impl<TP: TimeProvider> SyncJob<TP> {
	pub(crate) fn new(ival: Interval, utc_offset: UtcOffset) -> Self {
		SyncJob {
			schedule: JobSchedule::new(ival, utc_offset),
			job: None
		}
	}

	/// Specify a task to run, and schedule its next run
	pub fn run<F>(&mut self, f: F) -> &mut Self
	where
		F: 'static + FnMut() + Send
	{
		self.job = Some(Box::new(f));
		self.schedule.start_schedule();
		self
	}

	/// Run a task and re-schedule it. This is usually only called by
	/// [Scheduler::run_pending()](crate::Scheduler::run_pending).
	pub fn execute(&mut self, now: OffsetDateTime) {
		// Don't do anything if we're run out of runs
		if !self.schedule.can_run_again() {
			return;
		}
		if let Some(f) = &mut self.job {
			f();
		}
		self.schedule.schedule_next(now);
	}
}