Entity view (Content)

Overriding queue classes used in the Batch API in Drupal 7

By amcgowan
Aug. 10, 2015

There are lots of benefits in working with a platform such as Drupal, that come packed full of goodies for Drupal developers like myself and my colleagues, that enable us to build intelligent and innovative solutions. One of these benefits are the powerful APIs baked into Drupal core. The Batch API is one of these APIs. It enables the ability to perform a set of operations on one or more pieces of data allowing for what is sometimes a very cumbersome process to be streamlined and broken into multiple chunks. As a result, this decreases load on the server, reduces page timeouts and provides a better user experience to users who may encounter these lengthy processes.

At the core of the Batch API are queues. There are two kinds of queues in Drupal:

  • name: The name of the batch queue. This should be a unique name so that conflicts are not present when creating the queue item records itself in the {queue} database table (unless the implementation is designed primarily with this intent).
  • class: The name of the DrupalQueueInterface class to use when creating an instance of the batch’s queue class.

The purpose of the Batch API is to enable the ability for data or other operations to be processed and as a result, using queues as the foundation for the Batch API only made sense. However, the current implementations of both the reliable and non-reliable queues don’t always fit the requirements or provide the best technical implementation and therefore at times it is required for deriving the provided classes in Drupal core to implement a specialized queue class for handling the items in the batch itself.

When initializing a batch, the batch_set($batch_definition) function is invoked which takes a single parameter that contains the definition of the batch itself as an array. A batch definition contains important details about the batch itself such as the set of operations and data to process, a callback for when the batch is completed, default error and progress messages, and much more. However, the documentation does not paint a complete picture as it is missing one crucial piece of element that can be defined but is not required - the queueelement.

Hidden deep inside of the includes/form.inc, when a batch set is initialized (the batch queue is populated with operations to performed) or the batch set is being processed, the batch API initializes the queue class defined in the batch definition property queue. Due to Drupal’s method of setting the default queue class values, which is += array(‘queue’ => array( … )), it exposes the ability for developers to override the default queue class to be used by specifying a single element named queue as part of the $batch_definition parameter when invoking batch_set() as an array. The$batch_definition[‘queue’] element array requires two properties:

    • name: The name of the batch queue. This should be a unique name so that conflicts are not present when creating the queue item records itself in the {queue} database table (unless the implementation is designed primarily with this intent).
    • class: The name of the DrupalQueueInterface class to use when creating an instance of the batch’s queue class.

However, Drupal 7’s core does not implement any specialized batch queue interface and therefore it is important to make note that a concrete implementation of DrupalQueueInterface that is to be used as the class for the batch queue must also implement an additional method that the Batch API expects: public function getAllItems();. This method must return an array of all remaining items within the batch’s set of queue items that require to be processed.

An example of what standard interfaces could look like for the Batch API’s queue is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * Default queue interface for batch queues.
 */
interface DrupalBatchQueueInterface extends DrupalQueueInterface {
  /**
   * Returns the remaining items within the batch queue to process.
   *
   * @access public
   * @return array
   *   An array of remaining batch queue operations.
   */
  public function getAllItems();
}
 
/**
 * Reliable queue interface for batch queues.
 */
interface DrupalBatchReliableQueueInterface extends DrupalBatchQueueInterface, DrupalBatchReliableInterface {
   
}

 

This undocumented ability to override the queue classes used in the Batch API was uncovered in personal R&D work for a Drupal 7 installation profile that allows for inheritable install profiles to exist in a project named: Drupal InstallKit (note: the project is not complete nor is it “production” ready, but provides some interesting and experimental implementations for Drupal). As part of this installation profile which allows for derived (inherited) install profiles, the Drupal 7 install system was overwritten with custom handlers and in particular, I needed the ability to have named key elements as part of the batch operations instead of a numerical key representations of elements within the batch’s operation set (can be seen in the following commit: a64d434).

Lastly, I have reported this documentation bug within the Drupal.org’s documentation issue queue and which can be found here: https://www.drupal.org/node/2296445.

 

Post Tags: