Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Resque Ex Scheduler Laravel Package

kamisama/php-resque-ex-scheduler

A PHP port of Resque's scheduler that queues delayed background jobs for later execution. This extended fork adds scheduling support to php-resque, letting you enqueue jobs to run at a future time and keep Redis-backed workers processing them.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package alongside its worker companion (kamisama/php-resque-ex); it is archived, so add a vcs repository entry if Packagist resolution fails, and pin a tag:

composer require kamisama/php-resque-ex-scheduler kamisama/php-resque-ex

Look first at the bin/ directory (the scheduler entry point), lib/ResqueScheduler.php (the enqueueIn/enqueueAt API), and any bundled resque-scheduler-conf.php / sample schedule file. Run the entry point with --help to confirm the option names on this fork before wiring it into supervisor.

Create a single bootstrap that both your app and the scheduler/worker process include — it must register the autoloader, point Resque at Redis, and set the timezone:

require __DIR__ . '/vendor/autoload.php';
date_default_timezone_set('UTC');
Resque::setBackend('127.0.0.1:6379');

First use case — fire a one-off job 60 seconds from now from a web request, then run the two processes:

ResqueScheduler::enqueueIn(60, 'default', 'SendWelcomeEmail', ['user_id' => 42]);
# terminal 1 — the scheduler (polls Redis, enqueues due jobs)
php vendor/bin/resque-scheduler --verbose
# terminal 2 — a worker that actually executes the job class
php vendor/bin/resque-worker

Recurring jobs live in a schedule file (an array keyed by job name, each entry with cron, class, args, queue) that you pass to the scheduler; the job class itself is a normal Resque_Job-compatible class with a perform() method.

Implementation Patterns

Bootstrap-once, include-everywhere. Put setBackend, autoloading, logger setup, and timezone in one bootstrap.php and require it from the scheduler process, the worker process, and any web controller that schedules jobs. Divergent bootstraps are the top cause of "job scheduled but never ran" (wrong Redis DB, wrong queue, wrong class path).

Two scheduling styles. Use enqueueAt($unixTimestamp, $queue, $class, $args) when the wall-clock moment matters (billing cutoffs, reminders at a user's local time) and enqueueIn($seconds, ...) for relative UX delays. Precompute timestamps in the app layer rather than letting the scheduler guess.

Recurring via a schedule definition file. Keep recurring entries in one file (keyed by a stable job name, with cron, class, queue, args, and an optional human description). Keep that file under version control and treat it as deployable config — it is the single source of truth for periodic work.

Separate the queues. Route delayed one-offs to delayed and cron jobs to cron, then run dedicated workers per queue. This lets you scale cron workers independently, throttle noisy periodic jobs, and keep user-facing delayed work from queueing behind a slow nightly task.

Wrap scheduling in a service. Don't call ResqueScheduler::enqueue* from controllers directly; put it behind something like Scheduler::scheduleAt(...) so you can add logging, validation, and test doubles. You can assert against Redis directly in tests: the pending timestamps are sorted sets under the resque:delayed: key family.

Make every job idempotent. Delivery is at-least-once: a scheduler restart, a slow tick, or a worker crash-and-retry can produce duplicate execution. Guard with a Redis SETNX/lock or a unique business key inside perform().

Process management. Run both the scheduler and workers under supervisor/systemd with autorestart. One supervisor program per queue for workers, exactly one program for the scheduler. Pair with resque-web (from the Resque family) or direct redis-cli queries for operational visibility.

Gotchas and Tips

  • Archived since 2015. Treat it as legacy: PHP 7.4+/8 compatibility is not guaranteed, and the Resque_* global class names can collide with newer Resque forks. Pin versions, run the full stack in staging, and budget for a fork or a migration if you depend on it long-term.
  • Run exactly one scheduler. Two scheduler processes will double-enqueue every recurring job. Enforce via supervisor/pidfile, and use a Redis lock if you ever run it in a container that could scale.
  • Timing is approximate. The scheduler polls; a job is enqueued on the next tick after it becomes due, not exactly on the second. Cron * * * * * fires within seconds, not at :00.000. Don't design SLAs around sub-second precision.
  • Editing the schedule file requires a restart. The recurring definition is typically read at boot. Reload/restart the scheduler after changes, and roll it out as part of the deploy.
  • No cancellation API. To cancel a delayed job you must manipulate Redis yourself — ZREM from the delayed-timestamp index and from the per-timestamp sorted set. Encapsulate that in your service layer so you don't hand-edit keys ad hoc.
  • Redis persistence is mandatory. Delayed/recurring schedules live in Redis sorted sets. With AOF/RDB disabled, a Redis restart silently drops every pending schedule. Verify appendonly/save in production.
  • Timezone consistency. Cron evaluation and enqueueAt timestamps use the process timezone. Set date_default_timezone_set() identically in the app, worker, and scheduler bootstraps, or jobs will fire hours off.
  • Past timestamps. enqueueAt() with a timestamp already in the past fires on the next poll, not immediately — fine for catch-up, but don't rely on it for "run now" semantics.
  • Overlapping recurring jobs. A job slower than its cron interval will stack occurrences. Either shorten the work, add a Redis lock inside perform(), or check for an in-flight marker before enqueuing.
  • Silent failure by default. Turn on verbose logging in the bootstrap (route Resque_Log into your Monolog handler) and start the scheduler with --verbose. A misconfigured class name or queue name otherwise just leaves jobs sitting in a queue with no error surfaced.
  • Debug with redis-cli. Check resque:queues, resque:queue:<name>, and the resque:delayed:* sorted sets to distinguish "never enqueued" (scheduler problem) from "enqueued but not processed" (worker problem).
  • Cron dialect limits. Assume standard five-field cron; extensions like @daily or L/W modifiers may not be supported by the bundled parser. Test any non-trivial expression against the scheduler before relying on it.
  • Extension points. Subclass the job class for retry/failure hooks, and subclass or wrap ResqueScheduler if you need custom logging or pre-enqueue validation — both are plain PHP classes, so this is the safest way to add behaviour without patching the archived source.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator