VOOZH about

URL: https://deepwiki.com/hypervel/console/7.6-running-the-scheduler

⇱ Running the Scheduler | hypervel/console | DeepWiki


Loading...
Menu

Running the Scheduler

This document covers the ScheduleRunCommand class, which executes scheduled tasks. It explains the command's two execution modes (daemon and one-time), the event processing pipeline, background task management with coroutines, graceful shutdown mechanisms, and observability through event dispatching.

For information about defining schedules and registering events, see Schedule Registry. For details about event execution logic and lifecycle, see Event Execution and Lifecycle. For information about concurrency control and mutex management, see Concurrency and Mutex Management.

Command Overview

The ScheduleRunCommand is the primary execution engine for the task scheduling system. It continuously evaluates scheduled events and executes those that are due.

Command Signature:

schedule:run
 {--once : Run only once without looping}
 {--concurrency=60 : The number of background tasks to process at once}

Key Dependencies:

DependencyTypePurpose
ScheduleHypervel\Console\Scheduling\ScheduleProvides due events for execution
EventDispatcherInterfacePsr\EventDispatcher\EventDispatcherInterfaceDispatches lifecycle events for observability
CacheFactoryHypervel\Cache\Contracts\FactoryManages graceful shutdown flag
ExceptionHandlerHypervel\Foundation\Exceptions\Contracts\ExceptionHandlerReports event execution failures
ConcurrentHypervel\Coroutine\ConcurrentManages background task coroutine pool

Sources: src/Commands/ScheduleRunCommand.php26-71

Execution Modes

Daemon Mode

Daemon mode runs continuously in an infinite loop, checking for due events every 100ms. This is the default mode when the --once flag is omitted.


Daemon Loop Behavior:

  • Polling Interval: 100ms (100,000 microseconds) between each check cycle
  • Stop Flag Check: The shouldStop() method checks the cache every 1 second for the hypervel:schedule:stop flag
  • Initialization: Clears the stop flag on startup via clearShouldStop()
  • No Events Handling: Displays "No scheduled commands are ready to run, waiting..." once if no events are due

Sources: src/Commands/ScheduleRunCommand.php76-107 src/Commands/ScheduleRunCommand.php231-245 src/Commands/ScheduleRunCommand.php250-256

One-Time Mode

One-time mode executes all due events once and exits. This mode is designed for cron-based scheduling where an external cron job triggers the command at regular intervals.

Activation: Use the --once flag when invoking the command.

Execution Flow:

  1. Wraps event execution in a Waiter with unlimited timeout (-1)
  2. Calls runEvents() with all due events
  3. Waits for all events (including background tasks) to complete
  4. Exits with appropriate message

The Waiter class ensures that all background tasks spawned by events with runInBackground=true complete before the command exits.

Sources: src/Commands/ScheduleRunCommand.php84-87 src/Commands/ScheduleRunCommand.php123-135

Event Processing Pipeline

The event processing pipeline evaluates each due event through a series of filters and execution modes.


Pipeline Stages:

StageMethodPurpose
1. Repeat Checkevent->shouldRepeatNow()Prevents re-execution within the same minute for events with repeat intervals
2. Filter Evaluationevent->filtersPass(app)Evaluates environment filters, maintenance mode, and conditional callbacks
3. Single-Server Coordinationschedule->serverShouldRun()Acquires server mutex if onOneServer() is enabled
4. Execution Mode SelectionCheck event->runInBackgroundRoutes to foreground (blocking) or background (coroutine) execution

Sources: src/Commands/ScheduleRunCommand.php137-161 src/Commands/ScheduleRunCommand.php166-176

Single-Server Event Execution

For events marked with onOneServer(), the scheduler uses a SchedulingMutex to ensure only one server in a distributed deployment executes the event.

Flow:

  1. Call schedule->serverShouldRun(event, startedAt) to attempt mutex acquisition
  2. If successful, execute the event via runEvent()
  3. If another server holds the mutex, log skip message and continue

Sources: src/Commands/ScheduleRunCommand.php166-176

Background Task Management

The Concurrent class manages a bounded pool of coroutines for executing background tasks.


Concurrency Configuration:

  • Default Pool Size: 60 concurrent coroutines
  • Configuration: Set via --concurrency option
  • Behavior: Blocks when pool is full until a slot becomes available

Background vs Foreground Execution:

Execution ModeTriggered ByBehaviorUse Case
BackgroundrunInBackground()Non-blocking, spawns coroutineLong-running tasks, HTTP requests
ForegroundDefaultBlocking, executes in main loopQuick tasks, sequential dependencies

Sources: src/Commands/ScheduleRunCommand.php78-80 src/Commands/ScheduleRunCommand.php154-157

Event Execution Details

The runEvent() method handles the actual execution of a scheduled event and manages its lifecycle.


Execution Steps:

  1. Output Summary: Displays timestamp, command/closure description, and execution mode
  2. Dispatch Start Event: Fires ScheduledTaskStarting for observability
  3. Execute Event: Calls event->run(app) which handles mutex, callbacks, and command execution
  4. Dispatch Completion Event: Fires either ScheduledTaskFinished (with duration) or ScheduledTaskFailed (with exception)
  5. Error Handling: Reports exceptions via ExceptionHandler->report() but does not halt scheduler
  6. Output Completion: Displays timestamp, status (Finished/Failed), command, and duration

Exit Code Interpretation:

  • exitCode == 0: Success (displayed in green)
  • exitCode != 0: Failure (displayed in red)

Sources: src/Commands/ScheduleRunCommand.php181-226

Graceful Shutdown

The scheduler implements a cache-based graceful shutdown mechanism to coordinate stopping across distributed processes.


Shutdown Mechanism:

ComponentResponsibility
shouldStop()Checks cache every 1 second for stop flag, caches result
clearShouldStop()Deletes stop flag from cache on initialization
stop()Waits for concurrent pool to drain before exiting
Cache Keyhypervel:schedule:stop (boolean)

Shutdown Flow:

  1. External process (e.g., schedule:stop command) sets hypervel:schedule:stop to true in cache
  2. Main loop continues processing events until next stop check (max 1 second delay)
  3. shouldStop() detects flag and returns true
  4. Main loop exits
  5. stop() method polls concurrent->isEmpty() every 100ms
  6. Once all background tasks complete, scheduler exits

Optimization: The shouldStop() method caches the last check time to avoid excessive cache reads (throttled to 1-second intervals).

Sources: src/Commands/ScheduleRunCommand.php109-121 src/Commands/ScheduleRunCommand.php231-245 src/Commands/ScheduleRunCommand.php250-256

Observability and Event Dispatching

The scheduler dispatches PSR-14 events at key lifecycle points for monitoring and logging.

Event Lifecycle:


Dispatched Events:

Event ClassWhen DispatchedPayload
ScheduledTaskSkippedEvent fails filtersPass()Event $task
ScheduledTaskStartingBefore event->run()Event $task
ScheduledTaskFinishedAfter successful executionEvent $task, float $runtime
ScheduledTaskFailedAfter exception thrownEvent $task, Throwable $exception

Use Cases:

  • Monitoring: Track task execution frequency, duration, and failure rates
  • Alerting: Trigger notifications on task failures
  • Logging: Record execution history for audit trails
  • Metrics: Calculate scheduler health and performance metrics

Sources: src/Commands/ScheduleRunCommand.php145 src/Commands/ScheduleRunCommand.php199 src/Commands/ScheduleRunCommand.php206-209 src/Commands/ScheduleRunCommand.php213 src/Events/ScheduledTaskStarting.php1-19 src/Events/ScheduledTaskFailed.php1-21

Performance Characteristics

Polling Overhead:

  • Check Interval: 100ms (10 checks per second)
  • Cache Reads: 1 per second for stop flag (in daemon mode)
  • Event Evaluation: All due events checked every 100ms

Memory Considerations:

  • Concurrent Pool: Each background task holds a coroutine slot until completion
  • Pool Exhaustion: Blocks event processing when all slots are occupied
  • Recommendation: Set --concurrency based on expected concurrent task count

Latency:

  • Execution Delay: Max 100ms from event becoming due to execution start
  • Stop Latency: Max 1 second from stop signal to loop exit, plus concurrent pool drain time
  • One-Time Mode: No polling overhead, executes immediately and exits

Resource Usage:

  • CPU: Minimal during idle periods (Sleep blocks coroutine)
  • Cache Operations: ~1 read per second (stop flag check)
  • Event Dispatching: 2-3 events per executed task (Starting, Finished/Failed)

Sources: src/Commands/ScheduleRunCommand.php103 src/Commands/ScheduleRunCommand.php119 src/Commands/ScheduleRunCommand.php231-245