fluent_schedule

Crates.iofluent_schedule
lib.rsfluent_schedule
version1.0.1
created_at2025-11-08 20:04:09.698584+00
updated_at2025-11-10 12:21:24.538692+00
descriptionA human-readable, fluent task scheduling library for Rust.
homepage
repositoryhttps://github.com/Jacques-Murray/fluent_schedule
max_upload_size
id1923235
size56,096
Jacques Murray (Jacques-Murray)

documentation

README

Fluent Schedule

Rust CI Crates.io Documentation License: MIT

A human-readable, fluent task scheduling library for Rust. This library provides a simple API for scheduling tasks without using complex cron syntax.

Features

  • Fluent API: Chain methods to build schedules in a readable way
  • Flexible Scheduling: Support for intervals, specific times, and day-of-week scheduling
  • Type Safety: Compile-time guarantees for valid configurations
  • Error Handling: Clear error messages for invalid configurations
  • Zero Dependencies: Only depends on chrono for time handling
  • Thread Safe: Jobs can be safely shared across threads

Installation

Add this to your Cargo.toml:

[dependencies]
fluent_schedule = "1.0.0"

Quick Start

Basic Interval Scheduling

use fluent_schedule::{Job, Scheduler, FluentDuration};

fn main() {
    // Create a job that runs every 5 seconds
    let job = Job::new()
        .every(5u32.seconds())
        .run(|| println!("Task executed every 5 seconds!"));

    // Create and start the scheduler
    let mut scheduler = Scheduler::new();
    scheduler.add(job).expect("Failed to add job");

    // This blocks the current thread
    scheduler.run_forever();
}

Time-Based Scheduling

use fluent_schedule::{Job, Scheduler};
use chrono::Weekday;

fn main() {
    // Create a job that runs at 5:00 PM on weekdays
    let job = Job::new()
        .on_weekday()
        .at("17:00")
        .run(|| println!("End of workday!"));

    let mut scheduler = Scheduler::new();
    scheduler.add(job).expect("Failed to add job");

    scheduler.run_forever();
}

Multiple Jobs

use fluent_schedule::{Job, Scheduler, FluentDuration};
use chrono::Weekday;

fn main() {
    let job1 = Job::new()
        .every(10u32.seconds())
        .run(|| println!("Heartbeat every 10 seconds"));

    let job2 = Job::new()
        .on(Weekday::Mon)
        .at("09:00")
        .run(|| println!("Monday morning meeting"));

    let job3 = Job::new()
        .on_weekend()
        .at("10:00")
        .run(|| println!("Weekend task"));

    let mut scheduler = Scheduler::new();
    scheduler.add(job1).expect("Failed to add job1");
    scheduler.add(job2).expect("Failed to add job2");
    scheduler.add(job3).expect("Failed to add job3");

    scheduler.run_forever();
}

API Overview

Job Builder Methods

  • Job::new() - Create a new job
  • .every(duration) - Run at fixed intervals
  • .at(time_str) - Run at specific time (HH:MM or HH:MM:SS)
  • .on(weekday) - Run on specific days of the week
  • .on_weekday() - Run Monday through Friday
  • .on_weekend() - Run Saturday and Sunday
  • .run(closure) - Set the task to execute

Fluent Duration Extensions

The library extends unsigned integers with time unit methods:

use fluent_schedule::FluentDuration;

let five_seconds = 5u32.seconds();
let ten_minutes = 10u32.minutes();
let two_hours = 2u32.hours();

Scheduler Methods

  • Scheduler::new() - Create a new scheduler
  • .add(job) - Add a configured job (returns Result)
  • .run_forever() - Start the scheduler (blocks current thread)

Error Handling

The library uses SchedulerError for configuration issues:

use fluent_schedule::{Job, Scheduler, SchedulerError};

let invalid_job = Job::new().at("99:99").run(|| {});
let mut scheduler = Scheduler::new();

match scheduler.add(invalid_job) {
    Ok(()) => println!("Job added successfully"),
    Err(SchedulerError::InvalidTimeFormat(time)) => {
        eprintln!("Invalid time format: {}", time);
    }
    Err(SchedulerError::TaskNotSet) => {
        eprintln!("Job must have a task set with .run()");
    }
}

Examples

See the examples/ directory for more usage examples:

  • simple.rs - Basic usage with multiple job types

Run an example:

cargo run --example simple

Testing

Run the test suite:

cargo test

Run with verbose output:

cargo test --verbose

Documentation

Generate and view documentation:

cargo doc --open

Performance Considerations

  • The scheduler runs in a single thread and blocks on run_forever()
  • Jobs should be lightweight to avoid blocking other scheduled tasks
  • For CPU-intensive tasks, consider spawning threads within the job closure
  • The scheduler calculates sleep durations dynamically based on the next job's schedule

Limitations

  • Single-threaded execution (jobs run sequentially)
  • No persistence (schedules are lost on restart)
  • Time precision is limited to seconds
  • No support for complex cron-like expressions

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Changelog

See CHANGELOG.md for version history and changes.

Commit count: 0

cargo fmt