jiordiviera / laravel-smart-scheduler
A Laravel package for smart task scheduling
Installs: 18
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/jiordiviera/laravel-smart-scheduler
Requires
- php: ^8.2
- illuminate/console: ^11.0 || ^12.0
- illuminate/database: ^11.0 || ^12.0
- illuminate/events: ^11.0 || ^12.0
- illuminate/mail: ^11.0 || ^12.0
- illuminate/support: ^11.0 || ^12.0
Requires (Dev)
- laravel/pint: ^1.25
- orchestra/testbench: ^10.6
- pestphp/pest: ^4.1
- pestphp/pest-plugin-laravel: ^4.0
- rector/rector: ^2.2
This package is auto-updated.
Last update: 2025-12-08 12:26:36 UTC
README
A Laravel package for intelligent scheduled task management with observability, reliability features, and automatic stuck task detection.
Features
- Task Execution Tracking: Record every scheduled task execution with status, duration, and output
- Overlap Prevention: Automatically prevent concurrent executions of the same task
- Stuck Task Detection: Automatically detect and handle tasks that are stuck (server crash, process killed)
- Failure Notifications: Email notifications for failed and stuck tasks (extensible to other channels)
- Task History: Maintain execution history with server information
- Purge Command: Clean up old execution records
Requirements
- PHP 8.2+
- Laravel 11.x or 12.x
Installation
Install via Composer:
composer require jiordiviera/laravel-smart-scheduler
Publish the configuration and migrations:
php artisan vendor:publish --tag=smart-scheduler-config php artisan vendor:publish --tag=smart-scheduler-migrations
Run migrations:
php artisan migrate
Configuration
The package automatically registers a service provider. Configure settings in config/smart-scheduler.php:
return [ // Days to retain execution records 'purge_days' => 7, // Minutes before a task is considered stuck 'stuck_timeout_minutes' => 60, 'notifications' => [ 'email' => [ 'recipients' => ['admin@example.com'], ], 'notify_on_stuck' => true, ], ];
Or use environment variables:
SMART_SCHEDULER_PURGE_DAYS=7 SMART_SCHEDULER_STUCK_TIMEOUT=60 SMART_SCHEDULER_EMAIL_RECIPIENTS=admin@example.com,ops@example.com SMART_SCHEDULER_NOTIFY_STUCK=true
Usage
The package automatically tracks all scheduled tasks defined in routes/console.php:
use Illuminate\Support\Facades\Schedule; Schedule::command('backup:run')->daily(); Schedule::command('reports:generate')->hourly();
Viewing Execution History
Query the smart_schedule_runs table:
use Jiordiviera\SmartScheduler\LaravelSmartScheduler\Models\ScheduleRun; // Get recent executions $runs = ScheduleRun::latest('started_at')->limit(10)->get(); // Get failed executions $failed = ScheduleRun::where('status', ScheduleRun::STATUS_FAILED)->get(); // Get stuck executions $stuck = ScheduleRun::where('status', ScheduleRun::STATUS_STUCK)->get();
Purging Old Records
Remove old successful and ignored records:
# Purge records older than configured days php artisan smart-scheduler:purge # Purge with custom retention period php artisan smart-scheduler:purge --days=30 # Dry run to preview what would be deleted php artisan smart-scheduler:purge --dry-run
Detecting Stuck Tasks
Manually detect and mark stuck tasks:
# Detect stuck tasks (default: 60 minutes timeout) php artisan smart-scheduler:detect-stuck # Custom timeout php artisan smart-scheduler:detect-stuck --timeout=30 # Dry run (preview only) php artisan smart-scheduler:detect-stuck --dry-run # Without sending notifications php artisan smart-scheduler:detect-stuck --no-notify
Note: Stuck tasks are also automatically detected when a new execution of the same task starts.
Recommended Scheduler Setup
Add these commands to your routes/console.php for automatic maintenance:
use Illuminate\Support\Facades\Schedule; // Purge old records weekly Schedule::command('smart-scheduler:purge')->weekly(); // Detect stuck tasks every 30 minutes Schedule::command('smart-scheduler:detect-stuck')->everyThirtyMinutes();
How It Works
The package uses Laravel's event system to intercept scheduled task lifecycle:
┌─────────────────────────────────────────────────────────────────┐
│ Task Execution Flow │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ScheduledTaskStarting │
│ │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Check stuck │────▶│ Mark as stuck│ (if > timeout) │
│ │ tasks │ │ + notify │ │
│ └──────────────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Check overlap│────▶│ STATUS_IGNORED│ (if running) │
│ └──────────────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │STATUS_STARTING│ │
│ └──────────────┘ │
│ │ │
│ ▼ │
│ ScheduledTaskFinished │
│ │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Exit code = 0│────▶│STATUS_SUCCESS │ │
│ └──────────────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Exit code ≠ 0│────▶│STATUS_FAILED │ + notify │
│ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Task Statuses
| Status | Description |
|---|---|
starting |
Task is currently running |
success |
Task completed successfully (exit code 0) |
failed |
Task failed (exit code ≠ 0) |
ignored |
Task skipped due to overlap |
stuck |
Task was running too long and marked as stuck |
Extending Notifications
Implement SmartNotifierInterface to add custom notification channels:
use Jiordiviera\SmartScheduler\LaravelSmartScheduler\Contracts\SmartNotifierInterface; use Jiordiviera\SmartScheduler\LaravelSmartScheduler\Models\ScheduleRun; class SlackNotifier implements SmartNotifierInterface { public function sendFailureNotification(ScheduleRun $run): void { // Send to Slack } public function sendStuckNotification(ScheduleRun $run): void { // Send to Slack } }
Register in a service provider:
$this->app->singleton(SmartNotifierInterface::class, SlackNotifier::class);
Testing
composer test
Code Style
# Check composer pint # Fix composer pint:fix
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
The MIT License (MIT). Please see License File for more information.