=== modified file 'modules/system/system.queue.inc'
--- modules/system/system.queue.inc	2010-04-26 13:02:40 +0000
+++ modules/system/system.queue.inc	2010-06-07 07:02:17 +0000
@@ -24,7 +24,8 @@
  * DrupalQueueInterface::deleteItem(). If the consumer dies, the item will be
  * made available again by the DrupalQueueInterface implementation once the
  * lease expires. Another consumer will then be able to receive it when calling
- * DrupalQueueInterface::claimItem().
+ * DrupalQueueInterface::claimItem(). Due to this, the processing code should
+ * be aware that an item might be handed over for processing more than once.
  *
  * The $item object used by the DrupalQueueInterface can contain arbitrary
  * metadata depending on the implementation. Systems using the interface should
@@ -33,18 +34,29 @@
  * DrupalQueueInterface::claimItem() needs to be passed to
  * DrupalQueueInterface::deleteItem() once processing is completed.
  *
- * While the queue system makes a best effort to preserve order in messages,
- * due to the pluggable nature of the queue, there is no guarantee that items
- * will be delivered on claim in the order they were sent. For example, some
- * implementations like beanstalkd or others with distributed back-ends like
- * Amazon SQS will be managing jobs for a large set of producers and consumers
- * where a strict FIFO ordering will likely not be preserved.
+ * There are two kinds of queue backends available: strict, which preserves the
+ * order of messages and guarantees that every item will be executed at least
+ * once. The non-strict kind only does a best effort to preserve order in
+ * messages and to execute them at least once but there is a small chance that
+ * some items get lost. For example, some distributed back-ends like Amazon SQS
+ * will be managing jobs for a large set of producers and consumers where a
+ * strict FIFO ordering will likely not be preserved. Another example would be
+ * an in-memory queue backend which might lose items if it crashes. However,
+ * such a backend would be able to deal with significantly more writes than a
+ * strict queue and for many tasks this is more important. See aggregator_cron()
+ * for an example of how can this not be a problem. Another example is doing
+ * Twitter statistics -- the small possibility of losing a few items is
+ * insignificant next to power of the queue being able to keep up with writes.
+ * As described in the processing section, regardless of the queue being strict
+ * or not, the processing code should be aware that an item might be handed
+ * over for processing more than once.
  *
- * The system also makes no guarantees about a task only being executed once:
- * callers that have non-idempotent tasks either need to live with the
- * possiblity of the task being invoked multiple times in cases where a claim
- * lease expires, or need to implement their own transactions to make their
- * tasks idempotent.
+ * DrupalQueueInterface should be used to implement a non-strict queue and
+ * DrupalQueueStrictInterface to implement a strict queue. The functions
+ * signatures are the same but the caveats differ as described above.
+ *
+ * See DrupalQueue::get for the settings variables to choose which backend
+ * drives which queue.
  */
 
 /**
@@ -54,19 +66,35 @@ class DrupalQueue {
   /**
    * Get a queue object for a given name.
    *
+   * The following variables can be set by variable_set or $conf overrides:
+   * - queue_class_$name: the class to be used for the queue $name.
+   * - queue_default_class: the class to use when queue_class_$name is not
+   *   defined. Defaults to SystemQueue, a strict backend using SQL.
+   * - queue_default_strict_class: the class to use when queue_class_$name is
+   *   not defined and the queue_default_class is not strict. Defaults to
+   *   SystemQueue.
+   *
    * @param $name
    *   Arbitrary string. The name of the queue to work with.
+   * @param $strict
+   *   TRUE if the ordering of items and guaranteeing every item executes at
+   *   least once is important, FALSE if scalability is the main concern.
    * @return
    *   The queue object for a given name.
    */
-  public static function get($name) {
+  public static function get($name, $strict = FALSE) {
     static $queues;
     if (!isset($queues[$name])) {
       $class = variable_get('queue_class_' . $name, NULL);
       if (!$class) {
         $class = variable_get('queue_default_class', 'SystemQueue');
       }
-      $queues[$name] = new $class($name);
+      $object = new $class($name);
+      if ($strict && !$object instanceof DrupalQueueStrictInterface) {
+        $class = variable_get('queue_default_strict_class', 'SystemQueue');
+        $object = new $class($name);
+      }
+      $queues[$name] = $object;
     }
     return $queues[$name];
   }
@@ -89,8 +117,8 @@ interface DrupalQueueInterface {
    * @return
    *   TRUE if the item was successfully created and was (best effort) added
    *   to the queue, otherwise FALSE. We don't guarantee the item was
-   *   committed to disk, that your disk wasn't hit by a meteor, etc, but as
-   *   far as we know, the item is now in the queue.
+   *   committed to disk etc, but as far as we know, the item is now in the
+   *   queue.
    */
   public function createItem($data);
 
@@ -167,9 +195,18 @@ interface DrupalQueueInterface {
 }
 
 /**
+ * Strict queue interface.
+ *
+ * Classes implementing this interface preserve the order of messages and
+ * guarantee that every item will be executed at least once.
+ */
+interface DrupalQueueStrictInterface extends DrupalQueueInterface {
+}
+
+/**
  * Default queue implementation.
  */
-class SystemQueue implements DrupalQueueInterface {
+class SystemQueue implements DrupalQueueStrictInterface {
   /**
    * The name of the queue this instance is working with.
    *

