Skip to content

Latest commit

 

History

History
118 lines (73 loc) · 4.71 KB

README.textile

File metadata and controls

118 lines (73 loc) · 4.71 KB

MongoQueue

MongoQueue is a PHP queue that allows for moving tasks and jobs into an asynchronous process for completion in the background. The queue is managed by Mongo

MongoQueue is an extraction from online classifieds site Oodle. Oodle uses MongoQueue to background common tasks in order to keep page response times low.

Requirements

  • mongod 1.5.4+
  • PHP 5.3+
  • Mongo PECL (PHP mongo driver)

Installation

Extract the source files into a directory in your PHP library path. Because the queue is backed by Mongo, there is no need to migrate or set up a table for MongoQueue. It will use the mongo_queue collection in a database of your choice.

Usage

Before any MongoQueue actions are taken you’ll need to initialize the MongoQueue class with the proper settings:

 $mongo = new Mongo('mongodb://host:port',  array('connect' => false));
 MongoQueue::$connection = $mongo;
 MongoQueue::$database = 'my_database';

Jobs are PHP objects that extend from MongoJob. Object states are not serialized so jobs must be defined as public static function.

 require_once('MongoQueue/lib/MongoJob.php');
  
 class QueueTracer
   extends MongoJob
 {
   public static $context;
  
   public static function trace()
   {
     echo "Tracer hit\n";
   }
 }
  
 MongoQueue::push('QueueTracer', 'trace', array(), time() + 500); # run QueueTracer 500 seconds later

You can also take advantage of @MongoJob@’s built in later() method which automatically delays a method for asynchronous running:

QueueTracer::later(500)->trace();

You can also batch calls which have the same parameter so that they’ll only be run once by workers. The run time will be decided by the first job inserted and the subsequent jobs will not have their run times obeyed.

QueueTracer::batchLater(500)->trace();

MongoQueue also supports prioritization. Priorities are ascending and null (the default) is considered to have the lowerst priority.

QueueTracer::later(500, false, /*priority:*/ 1)->trace();

Running the jobs

Jobs are run via MongoQueue::run(). Before running job, you’ll need to set two extra MongoQueue initializers: environment and, optionally, context. MongoQueue currently does not include a daemon runner, but here is an example runner:

 $mongo = new Mongo('mongodb://host:port', array('connect' => false));
 MongoQueue::$connection = $mongo;
 MongoQueue::$database = 'my_database';
 MongoQueue::$environment = 'classes/jobs';
 MongoQueue::$context = array('context' => array('foo', 'bar'));

 if (MongoQueue::run())
     echo("Found a job to run");
 else
     echo("Nothing to run");

$environment is the path under which jobs are automatically loaded by the runner. The convention is that if your job class is called FooBar then the file that is loaded is $environment/FooBar.php

Any keys set in $context are available as static variables inside the Job class. (e.g. ‘context’ in the QueueTracer example)

Priorities

By default, MongoQueue will use priorites (which are all null by default). If you want to run the next job regardless of priority, you can pass false as the third param to run. e.g:

MongoQueue::run(null, null, false)

Administration

Indexing/Performance

You’ll want to add indices to MongoQueue to ensure high performance. You’ll need at least the following index for basic operation:

db.mongo_queue.ensureIndex({locked: 1, when: 1, priority: 1});

If you plan to use the batching feature you want an index on the type of jobs already in the queue:

 db.mongo_queue.ensureIndex({object_class: 1, object_method: 1, parameters: 1, locked: 1}); 

Sharding

MongoQueue comes with built-in support for manual sharding. Note that due to the key restriction on updates for auto-sharding, the ability to scale with only auto-sharding is limited.

If you initialize MongoQueue::$connection to an array instead of a single Mongo connection object, MongoQueue will insert or pull jobs at random from the set of connections. This way, you can have dedicated workers per physical machine and insert in a distributed way (or vice versa). For example:

 MongoQueue::$connection = array($mongo1, $mongo2, $mongo3, $mongo4);

MongoQueue will send batchable jobs to the same connection so that batched jobs with identical parameters will not be distribued across multiple mongo instances.

Monitoring

All jobs are stored as Mongo documents in the mongo_queue collection. MongoQueue does not come with any built in administrative scripts, but you can view the queue via your mongo console. locked_at will tell you whether or not a job is currently being processed.