[
  {
    "path": "CHANGELOG.md",
    "content": "## 1.1 (2013-03-11) ##\n\n**Note:** This release is compatible with php-resque 1.0 through 1.2.\n\n* Add composer.json and submit to Packagist (rayward)\n* Correct issues with documentation (Chuan Ma)\n* Update declarations for methods called statically to actually be static methods (atorres757)\n* Implement ResqueScheduler::removeDelayed and ResqueScheduler::removeDelayedJobFromTimestamp (tonypiper)\n* Correct spelling for ResqueScheduler_InvalidTimestampException (biinari)\n* Correct spelling of beforeDelayedEnqueue event (cballou)\n\n## 1.0 (2011-03-27) ##\n\n* Initial release"
  },
  {
    "path": "LICENSE",
    "content": "(c) 2012 Chris Boulton <chris@bigcommerce.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\t"
  },
  {
    "path": "README.md",
    "content": "php-resque-scheduler: PHP Resque Scheduler\n==========================================\n\nphp-resque-scheduler is a PHP port of [resque-scheduler](http://github.com/defunkt/resque),\nwhich adds support for scheduling items in the future to Resque.\n\nThe PHP port of resque-scheduler has been designed to be an almost direct-copy\nof the Ruby plugin, and is designed to work with the PHP port of resque,\n[php-resque](http://github.com/chrisboulton/php-resque).\n\nAt the moment, php-resque-scheduler only supports delayed jobs, which is the\nability to push a job to the queue and have it run at a certain timestamp, or\nin a number of seconds. Support for recurring jobs (similar to CRON) is planned\nfor a future release.\n\nBecause the PHP port is almost a direct API copy of the Ruby version, it is also\ncompatible with the web interface of the Ruby version, which provides the\nability to view and manage delayed jobs.\n\n## Delayed Jobs\n\nTo quote the documentation for the Ruby resque-scheduler:\n\n> Delayed jobs are one-off jobs that you want to be put into a queue at some\npoint in the future. The classic example is sending an email:\n\n    require 'Resque/Resque.php';\n    require 'ResqueScheduler/ResqueScheduler.php';\n   \n    $in = 3600;\n    $args = array('id' => $user->id);\n    ResqueScheduler::enqueueIn($in, 'email', 'SendFollowUpEmail', $args);\n\nThe above will store the job for 1 hour in the delayed queue, and then pull the\njob off and submit it to the `email` queue in Resque for processing as soon as\na worker is available.\n\nInstead of passing a relative time in seconds, you can also supply a timestamp\nas either a DateTime object or integer containing a UNIX timestamp to the\n`enqueueAt` method:\n\n\trequire 'Resque/Resque.php';\n    require 'ResqueScheduler/ResqueScheduler.php';\n    \n    $time = 1332067214;\n    ResqueScheduler::enqueueAt($time, 'email', 'SendFollowUpEmail', $args);\n\n\t$datetime = new DateTime('2012-03-18 13:21:49');\n\tResqueScheduler::enqueueAt($datetime, 'email', 'SendFollowUpEmail', $args);\n\nNOTE: resque-scheduler does not guarantee a job will fire at the time supplied.\nAt the time supplied, resque-scheduler will take the job out of the delayed\nqueue and push it to the appropriate queue in Resque. Your next available Resque\nworker will pick the job up. To keep processing as quick as possible, keep your\nqueues as empty as possible.\n\n## Worker\n\nLike resque, resque-scheduler includes a worker that runs in the background. This\nworker is responsible for pulling items off the schedule/delayed queue and adding\nthem to the queue for resque. This means that for delayed or scheduled jobs to be\nexecuted, the worker needs to be running.\n\nA basic \"up-and-running\" resque-scheduler.php file is included that sets up a\nrunning worker environment is included in the root directory. It accepts many\nof the same environment variables as php-resque:\n\n* `REDIS_BACKEND` - Redis server to connect to\n* `LOGGING` - Enable logging to STDOUT\n* `VERBOSE` - Enable verbose logging\n* `VVERBOSE` - Enable very verbose logging\n* `INTERVAL` - Sleep for this long before checking scheduled/delayed queues\n* `APP_INCLUDE` - Include this file when starting (to launch your app)\n* `PIDFILE` - Write the PID of the worker out to this file\n\nThe resque-scheduler worker requires resque to function. The demo\nresque-scheduler.php worker allows you to supply a `RESQUE_PHP` environment\nvariable with the path to Resque.php. If not supplied and resque is not already\nloaded, resque-scheduler will attempt to load it from your include path\n(`require_once 'Resque/Resque.php';'`)\n\nIt's easy to start the resque-scheduler worker using resque-scheduler.php:\n    $ RESQUE_PHP=../resque/lib/Resque/Resque.php php resque-scheduler.php\n\n## Event/Hook System\n\nphp-resque-scheduler uses the same event system used by php-resque and exposes\nthe following events.\n\n### afterSchedule\n\nCalled after a job has been added to the schedule. Arguments passed are the\ntimestamp, queue of the job, the class name of the job, and the job's arguments.\n\n### beforeDelayedEnqueue\n\nCalled immediately after a job has been pulled off the delayed queue and right\nbefore the job is added to the queue in resque. Arguments passed are the queue\nof the job, the class name of the job, and the job's arguments.\n\n## Contributors ##\n\n* chrisboulton\n* rayward\n* atorres757\n* tonypiper\n* biinari\n* cballou\n"
  },
  {
    "path": "composer.json",
    "content": "{\n\t\"name\": \"chrisboulton/php-resque-scheduler\",\n\t\"type\": \"library\",\n\t\"description\": \"php-resque-scheduler is a PHP port of resque-scheduler, which adds support for scheduling items in the future to Resque.\",\n\t\"license\": \"MIT\",\n\t\"authors\": [\n\t\t{\n\t\t\t\"name\": \"Chris Boulton\",\n\t\t\t\"email\": \"chris@bgigcommerce.com\"\n\t\t}\n\t],\n\t\"autoload\": {\n\t\t\"psr-0\": {\n\t\t\t\"ResqueScheduler\": \"lib/\"\n\t\t}\n\t},\n\t\"repositories\": [\n\t\t{ \"type\": \"git\", \"url\": \"https://github.com/chrisboulton/php-resque\" }\n\t],\n\t\"require\": {\n\t\t\"chrisboulton/php-resque\": \"dev-master\"\n\t}\n}\n"
  },
  {
    "path": "extras/resque-scheduler.monit",
    "content": "# Replace these with your own:\n# [PATH/TO/RESQUE]\n# [PATH/TO/RESQUE-SCHEDULER]\n# [UID]\n# [GID]\n# [APP_INCLUDE]\n\ncheck process resque-scheduler_worker\n  with pidfile /var/run/resque/scheduler-worker.pid\n  start program = \"/bin/sh -c 'APP_INCLUDE=[APP_INCLUDE] RESQUE_PHP=[PATH/TO/RESQUE] PIDFILE=/var/run/resque/scheduler-worker.pid nohup php -f [PATH/TO/RESQUE-SCHEDULER]/resque-scheduler.php > /var/log/resque/scheduler-worker.log &'\" as uid [UID] and gid [GID]\n  stop program = \"/bin/sh -c 'kill -s QUIT `cat /var/run/resque/scheduler-worker.pid` && rm -f /var/run/resque/scheduler-worker.pid; exit 0;'\"\n  if totalmem is greater than 300 MB for 10 cycles then restart  # eating up memory?\n  group resque-scheduler_workers"
  },
  {
    "path": "lib/ResqueScheduler/InvalidTimestampException.php",
    "content": "<?php\n/**\n* Exception thrown whenever an invalid timestamp has been passed to a job.\n*\n* @package\t\tResqueScheduler\n* @author\t\tChris Boulton <chris@bigcommerce.com>\n* @copyright\t(c) 2012 Chris Boulton\n* @license\t\thttp://www.opensource.org/licenses/mit-license.php\n*/\nclass ResqueScheduler_InvalidTimestampException extends Resque_Exception\n{\n\n}"
  },
  {
    "path": "lib/ResqueScheduler/Worker.php",
    "content": "<?php\n/**\n * ResqueScheduler worker to handle scheduling of delayed tasks.\n *\n * @package\t\tResqueScheduler\n * @author\t\tChris Boulton <chris@bigcommerce.com>\n * @copyright\t(c) 2012 Chris Boulton\n * @license\t\thttp://www.opensource.org/licenses/mit-license.php\n */\nclass ResqueScheduler_Worker\n{\n\tconst LOG_NONE = 0;\n\tconst LOG_NORMAL = 1;\n\tconst LOG_VERBOSE = 2;\n\t\n\t/**\n\t * @var int Current log level of this worker.\n\t */\n\tpublic $logLevel = 0;\n\t\n\t/**\n\t * @var int Interval to sleep for between checking schedules.\n\t */\n\tprotected $interval = 5;\n\t\n\t/**\n\t* The primary loop for a worker.\n\t*\n\t* Every $interval (seconds), the scheduled queue will be checked for jobs\n\t* that should be pushed to Resque.\n\t*\n\t* @param int $interval How often to check schedules.\n\t*/\n\tpublic function work($interval = null)\n\t{\n\t\tif ($interval !== null) {\n\t\t\t$this->interval = $interval;\n\t\t}\n\n\t\t$this->updateProcLine('Starting');\n\t\t\n\t\twhile (true) {\n\t\t\t$this->handleDelayedItems();\n\t\t\t$this->sleep();\n\t\t}\n\t}\n\t\n\t/**\n\t * Handle delayed items for the next scheduled timestamp.\n\t *\n\t * Searches for any items that are due to be scheduled in Resque\n\t * and adds them to the appropriate job queue in Resque.\n\t *\n\t * @param DateTime|int $timestamp Search for any items up to this timestamp to schedule.\n\t */\n\tpublic function handleDelayedItems($timestamp = null)\n\t{\n\t\twhile (($oldestJobTimestamp = ResqueScheduler::nextDelayedTimestamp($timestamp)) !== false) {\n\t\t\t$this->updateProcLine('Processing Delayed Items');\n\t\t\t$this->enqueueDelayedItemsForTimestamp($oldestJobTimestamp);\n\t\t}\n\t}\n\t\n\t/**\n\t * Schedule all of the delayed jobs for a given timestamp.\n\t *\n\t * Searches for all items for a given timestamp, pulls them off the list of\n\t * delayed jobs and pushes them across to Resque.\n\t *\n\t * @param DateTime|int $timestamp Search for any items up to this timestamp to schedule.\n\t */\n\tpublic function enqueueDelayedItemsForTimestamp($timestamp)\n\t{\n\t\t$item = null;\n\t\twhile ($item = ResqueScheduler::nextItemForTimestamp($timestamp)) {\n\t\t\t$this->log('queueing ' . $item['class'] . ' in ' . $item['queue'] .' [delayed]');\n\t\t\t\n\t\t\tResque_Event::trigger('beforeDelayedEnqueue', array(\n\t\t\t\t'queue' => $item['queue'],\n\t\t\t\t'class' => $item['class'],\n\t\t\t\t'args'  => $item['args'],\n\t\t\t));\n\n\t\t\t$payload = array_merge(array($item['queue'], $item['class']), $item['args']);\n\t\t\tcall_user_func_array('Resque::enqueue', $payload);\n\t\t}\n\t}\n\t\n\t/**\n\t * Sleep for the defined interval.\n\t */\n\tprotected function sleep()\n\t{\n\t\tsleep($this->interval);\n\t}\n\t\n\t/**\n\t * Update the status of the current worker process.\n\t *\n\t * On supported systems (with the PECL proctitle module installed), update\n\t * the name of the currently running process to indicate the current state\n\t * of a worker.\n\t *\n\t * @param string $status The updated process title.\n\t */\n\tprivate function updateProcLine($status)\n\t{\n\t\tif(function_exists('setproctitle')) {\n\t\t\tsetproctitle('resque-scheduler-' . ResqueScheduler::VERSION . ': ' . $status);\n\t\t}\n\t}\n\t\n\t/**\n\t * Output a given log message to STDOUT.\n\t *\n\t * @param string $message Message to output.\n\t */\n\tpublic function log($message)\n\t{\n\t\tif($this->logLevel == self::LOG_NORMAL) {\n\t\t\tfwrite(STDOUT, \"*** \" . $message . \"\\n\");\n\t\t}\n\t\telse if($this->logLevel == self::LOG_VERBOSE) {\n\t\t\tfwrite(STDOUT, \"** [\" . strftime('%T %Y-%m-%d') . \"] \" . $message . \"\\n\");\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "lib/ResqueScheduler.php",
    "content": "<?php\n/**\n* ResqueScheduler core class to handle scheduling of jobs in the future.\n*\n* @package\t\tResqueScheduler\n* @author\t\tChris Boulton <chris@bigcommerce.com>\n* @copyright\t(c) 2012 Chris Boulton\n* @license\t\thttp://www.opensource.org/licenses/mit-license.php\n*/\nclass ResqueScheduler\n{\n\tconst VERSION = \"0.1\";\n\t\n\t/**\n\t * Enqueue a job in a given number of seconds from now.\n\t *\n\t * Identical to Resque::enqueue, however the first argument is the number\n\t * of seconds before the job should be executed.\n\t *\n\t * @param int $in Number of seconds from now when the job should be executed.\n\t * @param string $queue The name of the queue to place the job in.\n\t * @param string $class The name of the class that contains the code to execute the job.\n\t * @param array $args Any optional arguments that should be passed when the job is executed.\n\t */\n\tpublic static function enqueueIn($in, $queue, $class, array $args = array())\n\t{\n\t\tself::enqueueAt(time() + $in, $queue, $class, $args);\n\t}\n\n\t/**\n\t * Enqueue a job for execution at a given timestamp.\n\t *\n\t * Identical to Resque::enqueue, however the first argument is a timestamp\n\t * (either UNIX timestamp in integer format or an instance of the DateTime\n\t * class in PHP).\n\t *\n\t * @param DateTime|int $at Instance of PHP DateTime object or int of UNIX timestamp.\n\t * @param string $queue The name of the queue to place the job in.\n\t * @param string $class The name of the class that contains the code to execute the job.\n\t * @param array $args Any optional arguments that should be passed when the job is executed.\n\t */\n\tpublic static function enqueueAt($at, $queue, $class, $args = array())\n\t{\n\t\tself::validateJob($class, $queue);\n\n\t\t$job = self::jobToHash($queue, $class, $args);\n\t\tself::delayedPush($at, $job);\n\t\t\n\t\tResque_Event::trigger('afterSchedule', array(\n\t\t\t'at'    => $at,\n\t\t\t'queue' => $queue,\n\t\t\t'class' => $class,\n\t\t\t'args'  => $args,\n\t\t));\n\t}\n\n\t/**\n\t * Directly append an item to the delayed queue schedule.\n\t *\n\t * @param DateTime|int $timestamp Timestamp job is scheduled to be run at.\n\t * @param array $item Hash of item to be pushed to schedule.\n\t */\n\tpublic static function delayedPush($timestamp, $item)\n\t{\n\t\t$timestamp = self::getTimestamp($timestamp);\n\t\t$redis = Resque::redis();\n\t\t$redis->rpush('delayed:' . $timestamp, json_encode($item));\n\n\t\t$redis->zadd('delayed_queue_schedule', $timestamp, $timestamp);\n\t}\n\n\t/**\n\t * Get the total number of jobs in the delayed schedule.\n\t *\n\t * @return int Number of scheduled jobs.\n\t */\n\tpublic static function getDelayedQueueScheduleSize()\n\t{\n\t\treturn (int)Resque::redis()->zcard('delayed_queue_schedule');\n\t}\n\n\t/**\n\t * Get the number of jobs for a given timestamp in the delayed schedule.\n\t *\n\t * @param DateTime|int $timestamp Timestamp\n\t * @return int Number of scheduled jobs.\n\t */\n\tpublic static function getDelayedTimestampSize($timestamp)\n\t{\n\t\t$timestamp = self::toTimestamp($timestamp);\n\t\treturn Resque::redis()->llen('delayed:' . $timestamp, $timestamp);\n\t}\n\n    /**\n     * Remove a delayed job from the queue\n     *\n     * note: you must specify exactly the same\n     * queue, class and arguments that you used when you added\n     * to the delayed queue\n     *\n     * also, this is an expensive operation because all delayed keys have tobe\n     * searched\n     *\n     * @param $queue\n     * @param $class\n     * @param $args\n     * @return int number of jobs that were removed\n     */\n    public static function removeDelayed($queue, $class, $args)\n    {\n       $destroyed=0;\n       $item=json_encode(self::jobToHash($queue, $class, $args));\n       $redis=Resque::redis();\n\n       foreach($redis->keys('delayed:*') as $key)\n       {\n           $key=$redis->removePrefix($key);\n           $destroyed+=$redis->lrem($key,0,$item);\n       }\n\n       return $destroyed;\n    }\n\n    /**\n     * removed a delayed job queued for a specific timestamp\n     *\n     * note: you must specify exactly the same\n     * queue, class and arguments that you used when you added\n     * to the delayed queue\n     *\n     * @param $timestamp\n     * @param $queue\n     * @param $class\n     * @param $args\n     * @return mixed\n     */\n    public static function removeDelayedJobFromTimestamp($timestamp, $queue, $class, $args)\n    {\n        $key = 'delayed:' . self::getTimestamp($timestamp);\n        $item = json_encode(self::jobToHash($queue, $class, $args));\n        $redis = Resque::redis();\n        $count = $redis->lrem($key, 0, $item);\n        self::cleanupTimestamp($key, $timestamp);\n\n        return $count;\n    }\n\t\n\t/**\n\t * Generate hash of all job properties to be saved in the scheduled queue.\n\t *\n\t * @param string $queue Name of the queue the job will be placed on.\n\t * @param string $class Name of the job class.\n\t * @param array $args Array of job arguments.\n\t */\n\n\tprivate static function jobToHash($queue, $class, $args)\n\t{\n\t\treturn array(\n\t\t\t'class' => $class,\n\t\t\t'args'  => array($args),\n\t\t\t'queue' => $queue,\n\t\t);\n\t}\n\n\t/**\n\t * If there are no jobs for a given key/timestamp, delete references to it.\n\t *\n\t * Used internally to remove empty delayed: items in Redis when there are\n\t * no more jobs left to run at that timestamp.\n\t *\n\t * @param string $key Key to count number of items at.\n\t * @param int $timestamp Matching timestamp for $key.\n\t */\n\tprivate static function cleanupTimestamp($key, $timestamp)\n\t{\n\t\t$timestamp = self::getTimestamp($timestamp);\n\t\t$redis = Resque::redis();\n\n\t\tif ($redis->llen($key) == 0) {\n\t\t\t$redis->del($key);\n\t\t\t$redis->zrem('delayed_queue_schedule', $timestamp);\n\t\t}\n\t}\n\n\t/**\n\t * Convert a timestamp in some format in to a unix timestamp as an integer.\n\t *\n\t * @param DateTime|int $timestamp Instance of DateTime or UNIX timestamp.\n\t * @return int Timestamp\n\t * @throws ResqueScheduler_InvalidTimestampException\n\t */\n\tprivate static function getTimestamp($timestamp)\n\t{\n\t\tif ($timestamp instanceof DateTime) {\n\t\t\t$timestamp = $timestamp->getTimestamp();\n\t\t}\n\t\t\n\t\tif ((int)$timestamp != $timestamp) {\n\t\t\tthrow new ResqueScheduler_InvalidTimestampException(\n\t\t\t\t'The supplied timestamp value could not be converted to an integer.'\n\t\t\t);\n\t\t}\n\n\t\treturn (int)$timestamp;\n\t}\n\n\t/**\n\t * Find the first timestamp in the delayed schedule before/including the timestamp.\n\t *\n\t * Will find and return the first timestamp upto and including the given\n\t * timestamp. This is the heart of the ResqueScheduler that will make sure\n\t * that any jobs scheduled for the past when the worker wasn't running are\n\t * also queued up.\n\t *\n\t * @param DateTime|int $timestamp Instance of DateTime or UNIX timestamp.\n\t *                                Defaults to now.\n\t * @return int|false UNIX timestamp, or false if nothing to run.\n\t */\n\tpublic static function nextDelayedTimestamp($at = null)\n\t{\n\t\tif ($at === null) {\n\t\t\t$at = time();\n\t\t}\n\t\telse {\n\t\t\t$at = self::getTimestamp($at);\n\t\t}\n\t\n\t\t$items = Resque::redis()->zrangebyscore('delayed_queue_schedule', '-inf', $at, array('limit' => array(0, 1)));\n\t\tif (!empty($items)) {\n\t\t\treturn $items[0];\n\t\t}\n\t\t\n\t\treturn false;\n\t}\t\n\t\n\t/**\n\t * Pop a job off the delayed queue for a given timestamp.\n\t *\n\t * @param DateTime|int $timestamp Instance of DateTime or UNIX timestamp.\n\t * @return array Matching job at timestamp.\n\t */\n\tpublic static function nextItemForTimestamp($timestamp)\n\t{\n\t\t$timestamp = self::getTimestamp($timestamp);\n\t\t$key = 'delayed:' . $timestamp;\n\t\t\n\t\t$item = json_decode(Resque::redis()->lpop($key), true);\n\t\t\n\t\tself::cleanupTimestamp($key, $timestamp);\n\t\treturn $item;\n\t}\n\n\t/**\n\t * Ensure that supplied job class/queue is valid.\n\t *\n\t * @param string $class Name of job class.\n\t * @param string $queue Name of queue.\n\t * @throws Resque_Exception\n\t */\n\tprivate static function validateJob($class, $queue)\n\t{\n\t\tif (empty($class)) {\n\t\t\tthrow new Resque_Exception('Jobs must be given a class.');\n\t\t}\n\t\telse if (empty($queue)) {\n\t\t\tthrow new Resque_Exception('Jobs must be put in a queue.');\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "resque-scheduler.php",
    "content": "<?php\n\n// Look for an environment variable with \n$RESQUE_PHP = getenv('RESQUE_PHP');\nif (!empty($RESQUE_PHP)) {\n\trequire_once $RESQUE_PHP;\n}\n// Otherwise, if we have no Resque then assume it is in the include path\nelse if (!class_exists('Resque')) {\n\trequire_once 'Resque/Resque.php';\n}\n\n// Load resque-scheduler\nrequire_once dirname(__FILE__) . '/lib/ResqueScheduler.php';\nrequire_once dirname(__FILE__) . '/lib/ResqueScheduler/Worker.php';\n\n$REDIS_BACKEND = getenv('REDIS_BACKEND');\n$REDIS_BACKEND_DB = getenv('REDIS_BACKEND_DB');\nif(!empty($REDIS_BACKEND)) {\n\tif (empty($REDIS_BACKEND_DB)) \n\t\tResque::setBackend($REDIS_BACKEND);\n\telse\n\t\tResque::setBackend($REDIS_BACKEND, $REDIS_BACKEND_DB);\n}\n\n// Set log level for resque-scheduler\n$logLevel = 0;\n$LOGGING = getenv('LOGGING');\n$VERBOSE = getenv('VERBOSE');\n$VVERBOSE = getenv('VVERBOSE');\nif(!empty($LOGGING) || !empty($VERBOSE)) {\n\t$logLevel = ResqueScheduler_Worker::LOG_NORMAL;\n}\nelse if(!empty($VVERBOSE)) {\n\t$logLevel = ResqueScheduler_Worker::LOG_VERBOSE;\n}\n\n// Check for jobs every $interval seconds\n$interval = 5;\n$INTERVAL = getenv('INTERVAL');\nif(!empty($INTERVAL)) {\n\t$interval = $INTERVAL;\n}\n\n// Load the user's application if one exists\n$APP_INCLUDE = getenv('APP_INCLUDE');\nif($APP_INCLUDE) {\n\tif(!file_exists($APP_INCLUDE)) {\n\t\tdie('APP_INCLUDE ('.$APP_INCLUDE.\") does not exist.\\n\");\n\t}\n\n\trequire_once $APP_INCLUDE;\n}\n\n$PREFIX = getenv('PREFIX');\nif(!empty($PREFIX)) {\n    fwrite(STDOUT, '*** Prefix set to '.$PREFIX.\"\\n\");\n    Resque_Redis::prefix($PREFIX);\n}\n\n$worker = new ResqueScheduler_Worker();\n$worker->logLevel = $logLevel;\n\n$PIDFILE = getenv('PIDFILE');\nif ($PIDFILE) {\n\tfile_put_contents($PIDFILE, getmypid()) or\n\t\tdie('Could not write PID information to ' . $PIDFILE);\n}\n\nfwrite(STDOUT, \"*** Starting scheduler worker\\n\");\n$worker->work($interval);\n"
  }
]