clockwork_schedule

Package Version Hex Docs

A robust scheduling extension for the Clockwork library that provides a clean, type-safe way to define and manage recurring tasks with built-in OTP supervision support in Gleam applications.

Features

Installation

gleam add clockwork_schedule@1

Quick Start

import clockwork
import clockwork_schedule
import gleam/io

pub fn main() {
  // Create a cron expression (runs every 5 minutes)
  let assert Ok(cron) = clockwork.from_string("*/5 * * * *")
  
  // Define your job
  let job = fn() { io.println("Task executed!") }
  
  // Create and start the scheduler
  let scheduler = clockwork_schedule.new("my_task", cron, job)
  let assert Ok(schedule) = clockwork_schedule.start(scheduler)
  
  // The task will run every 5 minutes until stopped
  // Stop when done
  clockwork_schedule.stop(schedule)
}

Usage Examples

Basic Scheduled Task

import clockwork
import clockwork_schedule

pub fn hourly_cleanup() {
  let assert Ok(cron) = clockwork.from_string("0 * * * *")  // Every hour
  
  let scheduler = 
    clockwork_schedule.new("cleanup", cron, fn() {
      // Your cleanup logic here
      delete_old_temp_files()
      compress_logs()
    })
  
  let assert Ok(schedule) = clockwork_schedule.start(scheduler)
  // Returns a Schedule handle for control
}

With Logging Enabled

let scheduler = 
  clockwork_schedule.new("data_sync", cron, sync_function)
  |> clockwork_schedule.with_logging()  // Enable execution logging

// Logs will show:
// [CLOCKWORK] Running job: data_sync at 1706025600.0
// [CLOCKWORK] Stopping job: data_sync

Time Zone Configuration

import gleam/time/duration

// Configure for UTC+9 (Tokyo)
let tokyo_offset = duration.hours(9)

let tokyo_scheduler = 
  clockwork_schedule.new("tokyo_report", cron, generate_report)
  |> clockwork_schedule.with_time_offset(tokyo_offset)

// Configure for UTC-5 (New York)
let ny_offset = duration.hours(-5)

let ny_scheduler = 
  clockwork_schedule.new("ny_report", cron, generate_report)
  |> clockwork_schedule.with_time_offset(ny_offset)

Supervised Scheduling (Recommended for Production)

import clockwork
import clockwork_schedule
import gleam/erlang/process
import gleam/otp/static_supervisor as supervisor

pub fn main() {
  let assert Ok(cron) = clockwork.from_string("0 0 * * *")  // Daily at midnight
  
  let scheduler = 
    clockwork_schedule.new("daily_backup", cron, backup_database)
    |> clockwork_schedule.with_logging()
  
  // Create a receiver for the schedule handle
  let schedule_receiver = process.new_subject()
  
  // Create the child specification
  let child_spec = 
    clockwork_schedule.supervised(scheduler, schedule_receiver)
  
  // Add to supervision tree
  let assert Ok(sup) =
    supervisor.new(supervisor.OneForOne)
    |> supervisor.add(child_spec)
    |> supervisor.start()
  
  // Receive the schedule handle
  let assert Ok(schedule) = process.receive(schedule_receiver, 1000)
  
  // The scheduler is now running under supervision
  // It will automatically restart if it crashes
}

Multiple Concurrent Schedulers

pub fn start_all_schedulers() {
  // Metrics collection every 5 minutes
  let assert Ok(metrics_cron) = clockwork.from_string("*/5 * * * *")
  let metrics_scheduler = 
    clockwork_schedule.new("metrics", metrics_cron, collect_metrics)
  
  // Database backup every day at 2 AM
  let assert Ok(backup_cron) = clockwork.from_string("0 2 * * *")
  let backup_scheduler = 
    clockwork_schedule.new("backup", backup_cron, backup_database)
  
  // Cache cleanup every hour
  let assert Ok(cache_cron) = clockwork.from_string("0 * * * *")
  let cache_scheduler = 
    clockwork_schedule.new("cache", cache_cron, clear_cache)
  
  // Start all schedulers
  let assert Ok(metrics_schedule) = clockwork_schedule.start(metrics_scheduler)
  let assert Ok(backup_schedule) = clockwork_schedule.start(backup_scheduler)
  let assert Ok(cache_schedule) = clockwork_schedule.start(cache_scheduler)
  
  // All three schedulers now run independently
  #(metrics_schedule, backup_schedule, cache_schedule)
}

Cron Expression Format

This library uses the Clockwork library for cron expression parsing:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ minute (0 - 59)
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ hour (0 - 23)
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ day of the month (1 - 31)
β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ month (1 - 12)
β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ day of the week (0 - 6) (Sunday to Saturday)
β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚
* * * * *

Common Patterns

PatternDescriptionExample
* * * * *Every minuteRuns at :00, :01, :02, etc.
*/5 * * * *Every 5 minutesRuns at :00, :05, :10, etc.
0 * * * *Every hourRuns at the top of each hour
0 0 * * *Daily at midnightRuns at 00:00
0 0 * * 0Weekly on SundayRuns Sunday at midnight
0 0 1 * *Monthly on the 1stRuns on the 1st at midnight
30 2 * * 1-5Weekdays at 2:30 AMMon-Fri at 02:30
0 */4 * * *Every 4 hoursRuns at 00:00, 04:00, 08:00, etc.
0 9-17 * * 1-5Business hoursMon-Fri, every hour 9 AM - 5 PM

Architecture

Actor Model

Each scheduler runs as an independent actor, ensuring:

Job Execution

Supervision Tree Integration

When supervised:

Testing

Run the test suite:

gleam test

The test suite covers:

Performance Considerations

Best Practices

  1. Use Supervision in Production

    • Always use supervised/2 for production deployments
    • Ensures reliability and automatic recovery
  2. Enable Logging for Critical Jobs

    • Use with_logging/1 for important scheduled tasks
    • Helps with debugging and monitoring
  3. Handle Errors in Jobs

    • Wrap job logic in proper error handling
    • Log failures for investigation
  4. Time Zone Awareness

    • Use with_time_offset/2 for time-zone-specific scheduling
    • Consider daylight saving time changes
  5. Resource Cleanup

    • Always call stop/1 when shutting down
    • Ensures clean termination

Troubleshooting

Job Not Running

Memory Issues

Supervision Restarts

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Write tests for new functionality
  4. Ensure all tests pass (gleam test)
  5. Commit changes (git commit -m 'Add amazing feature')
  6. Push to branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

Development Setup

# Clone the repository
git clone https://github.com/renatillas/clockwork_schedule.git
cd clockwork_schedule

# Install dependencies
gleam deps download

# Run tests
gleam test

# Format code
gleam format

# Build documentation
gleam docs build

Related Projects

Support

✨ Search Document