ldkafka / yii2-scheduler
High-resolution cron-like job scheduler for Yii2 supporting daemon and external cron modes, queue integration, single-instance locks, and drift correction.
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/ldkafka/yii2-scheduler
Requires
- php: >=8.0
- yiisoft/yii2: ~2.0.14
- yiisoft/yii2-queue: ~2.3.0
README
High-resolution cron-like job scheduler for Yii2 supporting:
- External cron mode (invoke the scheduler from system cron, typically every minute)
- Daemon mode (single long-running loop with microsecond timing and drift correction)
- Queue integration (yii2-queue) or synchronous execution
- Single-instance locks with max running time and stale lock reclamation
- Atomic distributed locks (cache add) with metadata:
{pid, host, ts} - Robust cron pattern parsing: wildcards, ranges, steps, lists
Installation
- Require the package (after you publish it to a VCS):
composer require ldkafka/yii2-scheduler
- Configure in your Yii2 console app (e.g.
console/config/main.php):
return [ 'bootstrap' => [ // ensure the component can bootstrap its controller 'scheduler', ], 'components' => [ 'cache' => [ /* your cache config */ ], 'queue_scheduler' => [ /* your yii2-queue config */ ], 'scheduler' => [ 'class' => ldkafka\scheduler\Scheduler::class, 'config' => [ 'cache' => 'cache', // optional; default 'cache' (uses Yii::$app->cache) 'queue' => 'queue_scheduler', // optional; omit to run inline synchronously ], 'jobs' => require __DIR__ . '/scheduler.php', ], ], ];
- Create
console/config/scheduler.phpwith your jobs:
<?php use ldkafka\scheduler\ScheduledJob; return [ [ 'class' => \common\jobs\ExampleJob::class, // must extend ScheduledJob 'run' => 'EVERY_MINUTE', 'single_instance' => true, // default true 'max_running_time' => 300, // seconds; 0 = unlimited ], [ 'class' => \common\jobs\NightlyJob::class, 'run' => [ 'minutes' => 0, 'hours' => 2, 'wday' => '1-5', // Mon-Fri ], ], ];
Usage
- External cron mode:
php yii scheduler/run
- Daemon mode (long-running with drift correction):
php yii scheduler/daemon
Upgrade notes
Upgrading from 1.0.3 or earlier
- Lock format changed: Locks now store
{pid, host, ts}instead of bare PID. No migration needed; old locks will expire naturally (1-hour TTL). - Config cleanup: Remove obsolete
staleLockTtlandmaxJobsPerTickfrom your scheduler config (not implemented). - Cron parsing improved: The
daykey is now normalized tomday. Update job configs usingdayto usemdayinstead for clarity. - Log levels adjusted: Normal flow messages moved from warning→info. Review log filters if you relied on warning-level job execution logs.
Release checklist
- Symbolic:
EVERY_MINUTE,EVERY_HOUR,EVERY_DAY,EVERY_WEEK,EVERY_MONTH - Cron-like array using
getdate()keys:minutes,hours,mday(day of month),wday(weekday),mon,year- Patterns per key:
*- wildcard (matches any value)5- exact match*/5- step/interval (every 5th unit: 0, 5, 10...)1-5- range (1 through 5 inclusive)10-20/2- range with step (10, 12, 14, 16, 18, 20)1,3,5- list (matches 1 or 3 or 5)
- Multiple patterns can be combined with commas for OR semantics
- Patterns per key:
Writing a job
namespace common\jobs; use ldkafka\scheduler\ScheduledJob; use Yii; class ExampleJob extends ScheduledJob { public function execute($queue = null) { Yii::info('ExampleJob executed', 'scheduler'); // do work return true; // success } }
Notes:
- When using queue mode, jobs are pushed to the configured queue component and executed by a queue worker.
- Locks use metadata format
{pid: int, host: string, ts: int}and are acquired atomically withcache->add(). - Stale lock reclamation: if the scheduler finds an existing lock with no running jobs in cache, it safely re-reads and deletes the lock before retrying (prevents race conditions).
- Stale jobs exceeding
max_running_timeare auto-removed from the run cache; if the queue driver supportsremove(), the queued job is also removed. max_running_timeis enforced during scheduler ticks; consider queueing long-running jobs for better concurrency.
Logging
All logs use the scheduler category with production-appropriate levels:
- info: Normal operations (job selected, queued, executed, lock acquired/released)
- warning: Anomalies worth attention (stale lock removed, job exceeded max time, single-instance conflict, queue check failure)
- error: Failures requiring intervention (cache lock acquisition failed, job class not found, queue push failed, critical init errors)
Configure a log target in your console/config/main.php if needed:
'log' => [ 'targets' => [ [ 'class' => 'yii\log\FileTarget', 'levels' => ['error', 'warning', 'info'], 'categories' => ['scheduler'], 'logFile' => '@runtime/logs/scheduler.log', 'maxFileSize' => 10240, // 10 MB ], ], ],
Cleanup and safety
- All jobs are executed via a SafeJobWrapper that catches exceptions and prevents worker crashes.
- On completion (sync or async), the wrapper will call
Scheduler::finalizeRuntimeJob()to remove the job entry from the persistent run cache.
Compatibility
- Requires PHP >= 8.0, Yii2 ~2.0.14
- Optional
pcntlfor graceful signal handling (SIGINT/SIGTERM). On platforms withoutpcntl, the daemon stops when too many ticks are missed (configurable).
License
BSD-3-Clause