Overview

Architecture

WPZylos Scheduler provides a fluent task scheduling layer on top of WordPress's WP-Cron system. It follows a registry pattern where a central Schedule object manages a collection of ScheduledTask instances.

Component Diagram

┌──────────────────────────────────────────────────────────┐
|                  SchedulerServiceProvider                |
|  - Registers Schedule singleton                          |
|  - Hooks into WP-Cron (every-minute interval)            |
|  - Runs due tasks on cron trigger                        |
+--──────────────────────┬─────────────────────────────────┘
                         |
                         ▼
┌──────────────────────────────────────────────────────────┐
|                       Schedule                           |
|  - call(callable): ScheduledTask                         |
|  - command(string): ScheduledTask                        |
|  - job(string): ScheduledTask                            |
|  - getTasks(): ScheduledTask[]                           |
|  - getDueTasks(): ScheduledTask[]                        |
|  - run(): int                                            |
+--──────────────────────┬─────────────────────────────────┘
                         | manages
                         ▼
┌──────────────────────────────────────────────────────────┐
|                    ScheduledTask                          |
|  uses: Frequencies, ManagesLocks                         |
|  - name(), when(), skip(), between(), onOneServer()      |
|  - isDue(): bool                                         |
|  - run(): void                                           |
+--────────┬───────────────────────────────┬───────────────┘
           |                               |
           ▼                               ▼
┌─────────────────────┐     ┌──────────────────────────────┐
|    Frequencies       |     |       ManagesLocks           |
|  everyMinute()       |     |  withoutOverlapping()        |
|  everyFiveMinutes()  |     |  acquireLock() / releaseLock |
|  hourly() / daily()  |     |  (uses WP transients)        |
|  weekly() / monthly() |     +--────────────────────────────┘
+--───────────────────┘

Design Patterns

Registry Pattern

The Schedule class acts as a registry, collecting all task definitions. Tasks are registered via call(), command(), and job() methods, each returning a ScheduledTask for fluent configuration.

Fluent Interface

Every configuration method on ScheduledTask returns static, enabling natural chaining:

$schedule->call($callback)
    ->everyFiveMinutes()
    ->name('my-task')
    ->withoutOverlapping()
    ->between('09:00', '17:00')
    ->when(fn() => is_main_site());

Trait Composition

Scheduling concerns are split into focused traits:

  • Frequencies — All time-based frequency methods and interval tracking
  • ManagesLocks — Transient-based overlap prevention logic

Strategy Pattern

The ScheduledTask::run() method uses a match expression to execute the appropriate strategy based on task type (callback, command, job).

How It Works

  1. Registration — The SchedulerServiceProvider registers a Schedule singleton in the container
  2. Cron Hook — A custom every_minute cron schedule is added via cron_schedules filter
  3. Execution — On each WP-Cron tick, the provider resolves the Schedule and calls run()
  4. Due Checkrun() iterates all tasks, calling isDue() on each to check time/condition constraints
  5. Lock Check — If withoutOverlapping() is enabled, a transient lock is checked before execution
  6. Task Run — The task executes based on its type: closure call, WP-CLI command, or job dispatch

Integration with WP-Cron

The scheduler hooks into WordPress's native cron system:

// 1. Register a custom every-minute interval
add_filter('cron_schedules', function ($schedules) {
    $schedules['wpzylos_every_minute'] = [
        'interval' => 60,
        'display'  => 'Every Minute',
    ];
    return $schedules;
});

// 2. Schedule the recurring event
wp_schedule_event(time(), 'wpzylos_every_minute', 'wpzylos_run_scheduler');

// 3. Run due tasks on the cron action
add_action('wpzylos_run_scheduler', function () use ($app) {
    $app->make(Schedule::class)->run();
});

Note: For production reliability, configure a system-level cron job to hit wp-cron.php every minute and disable WordPress's default "on-request" cron with define('DISABLE_WP_CRON', true);.