toflar/cronjob-supervisor
Run and cap background workers using only a minutely cronjob—no supervisord needed. Define commands with desired concurrency; the supervisor tracks running processes and prevents overspawning across minutes via ps/tasklist/flock providers, working on Linux and Windows.
## Getting Started
### Minimal Setup
1. **Installation**
```bash
composer require toflar/cronjob-supervisor
Publish the config file (if needed):
php artisan vendor:publish --provider="Toflar\CronjobSupervisor\CronjobSupervisorServiceProvider"
Basic Configuration
Edit config/cronjob-supervisor.php to define your cron jobs:
'jobs' => [
'send-daily-reports' => [
'command' => 'php artisan reports:send',
'schedule' => '0 8 * * *',
'description' => 'Send daily reports to users',
],
],
First Use Case
Register the supervisor in app/Console/Kernel.php:
protected function schedule(Schedule $schedule)
{
$schedule->job(new \Toflar\CronjobSupervisor\CronjobSupervisorJob());
}
Run the supervisor manually for testing:
php artisan schedule:run
Cron Job Management
crontab entries.'process-invoices' => [
'command' => 'php artisan invoices:process',
'schedule' => '*/15 * * * *',
'before' => ['check-payments'],
'after' => ['log-invoices'],
],
Dynamic Scheduling
Schedule facade to dynamically adjust job timing:
$schedule->job(new \Toflar\CronjobSupervisor\CronjobSupervisorJob())
->everyMinute()
->when(function () {
return config('app.env') === 'production';
});
Logging and Monitoring
CronjobSupervisorJob:
use Toflar\CronjobSupervisor\CronjobSupervisorJob;
use Illuminate\Support\Facades\Log;
class CustomCronjobSupervisorJob extends CronjobSupervisorJob
{
protected function logJobExecution($jobName, $result)
{
Log::info("Cronjob executed: {$jobName}. Result: " . ($result ? 'Success' : 'Failed'));
}
}
Environment-Specific Jobs
'jobs' => [
'cleanup-temp-files' => [
'command' => 'php artisan temp:clean',
'schedule' => '0 3 * * *',
'environments' => ['staging', 'production'],
],
],
Cron Syntax Errors
schedule is correct (e.g., * * * * * for every minute). Test with crontab.guru.php artisan tinker to validate schedules:
\Illuminate\Support\Facades\Schedule::call('send-daily-reports');
Missing Dependencies
before/after dependencies, ensure all referenced jobs exist in the config. Missing jobs will silently fail.$this->validateCronJobs(config('cronjob-supervisor.jobs'));
Time Zone Mismatches
.env:
APP_TIMEZONE=America/New_York
now()->timezone('UTC')->format('Y-m-d H:i:s') for consistent logging.Artisan Command Failures
command fails, the supervisor logs the exit code but doesn’t retry by default.Schedule::call() with custom timing logic instead of cron syntax.Custom Job Handlers
CronjobSupervisorJob to add pre/post hooks:
class ExtendedSupervisorJob extends CronjobSupervisorJob
{
protected function beforeJob($jobName)
{
// Pre-execution logic (e.g., check DB connection)
}
protected function afterJob($jobName, $result)
{
// Post-execution logic (e.g., send Slack alert)
}
}
Database-Backed Scheduling
cron_jobs) and fetch them dynamically:
$jobs = DB::table('cron_jobs')->where('active', 1)->get();
foreach ($jobs as $job) {
$schedule->command($job->command)->everyMinute();
}
Slack/Email Notifications
use Illuminate\Support\Facades\Notification;
use App\Notifications\CronjobFailed;
protected function afterJob($jobName, $result)
{
if (!$result) {
Notification::route('mail', 'admin@example.com')
->notify(new CronjobFailed($jobName));
}
}
Docker/Serverless Considerations
cron: true in docker-compose.yml).APP_DEBUG=true) and check storage/logs/laravel.log.php artisan schedule:work to manually trigger jobs without waiting for cron.1 for command failure) in logs.Log::debug("Job '{$jobName}' executed at: " . now()->toDateTimeString());
NO_UPDATE_NEEDED would not apply here due to the meaningful addition of precision improvements in the new release.
How can I help you explore Laravel packages today?