Commit 7be75b46 authored by catch's avatar catch

Issue #1814496 by Berdir, deviance, Lars Toomre: Make queue a container service.

parent 65e54edb
......@@ -958,7 +958,7 @@ function drupal_get_filename($type, $name, $filename = NULL) {
* The settings object.
*/
function settings() {
return Settings::$singleton;
return Settings::getSingleton();
}
/**
......
......@@ -6719,9 +6719,9 @@ function drupal_get_filetransfer_info() {
* @param string $name
* The name of the queue to work with.
* @param bool $reliable
* TRUE if the ordering of items and guaranteeing every item executes at
* least once is important, FALSE if scalability is the main concern. Defaults
* to FALSE.
* (optional) TRUE if the ordering of items and guaranteeing every item
* executes at least once is important, FALSE if scalability is the main
* concern. Defaults to FALSE.
*
* @return Drupal\Core\Queue\QueueInterface
* The queue object for a given name.
......@@ -6729,18 +6729,7 @@ function drupal_get_filetransfer_info() {
* @see Drupal\Core\Queue\QueueInterface
*/
function queue($name, $reliable = FALSE) {
static $queues;
if (!isset($queues[$name])) {
$class = variable_get('queue_class_' . $name, NULL);
if ($class && $reliable && in_array('Drupal\Core\Queue\ReliableQueueInterface', class_implements($class))) {
$class = variable_get('queue_default_reliable_class', 'Drupal\Core\Queue\System');
}
elseif (!$class) {
$class = variable_get('queue_default_class', 'Drupal\Core\Queue\System');
}
$queues[$name] = new $class($name);
}
return $queues[$name];
return drupal_container()->get('queue')->get($name, $reliable);
}
/**
......
......@@ -6,8 +6,9 @@
*/
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Utility\Color;
use Drupal\Core\Database\Database;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Utility\Color;
/**
* @defgroup forms Form builder functions
......@@ -5204,7 +5205,7 @@ function _batch_queue($batch_set) {
$class = $batch_set['queue']['class'];
if (!isset($queues[$class][$name])) {
$queues[$class][$name] = new $class($name);
$queues[$class][$name] = new $class($name, Database::getConnection());
}
return $queues[$class][$name];
}
......
......@@ -2,29 +2,51 @@
/**
* @file
* Contains Drupal\Component\Utility\Settings.
* Contains \Drupal\Component\Utility\Settings.
*/
namespace Drupal\Component\Utility;
class Settings {
/**
* Read only settings that are initialized with the class.
*/
final class Settings {
/**
* Array with the settings.
*
* @var array
*/
protected $storage;
private $storage = array();
/**
* @var Settings
* Singleton instance.
*
* @var \Drupal\Component\Utility\Settings
*/
static $singleton;
private static $instance;
/**
* Returns the settings instance.
*
* A singleton is used because this class is used before the container is
* available.
*
* @return \Drupal\Component\Utility\Settings
*/
public static function getSingleton() {
return self::$instance;
}
/**
* Constructor.
*
* @param array $settings
* Array with the settings.
*/
function __construct(array $settings) {
$this->storage = $settings;
self::$singleton = $this;
self::$instance = $this;
}
/**
......
......@@ -73,6 +73,19 @@ public function build(ContainerBuilder $container) {
->register('keyvalue.database', 'Drupal\Core\KeyValueStore\KeyValueDatabaseFactory')
->addArgument(new Reference('database'));
$container->register('settings', 'Drupal\Component\Utility\Settings')
->setFactoryClass('Drupal\Component\Utility\Settings')
->setFactoryMethod('getSingleton');
// Register the Queue factory.
$container
->register('queue', 'Drupal\Core\Queue\QueueFactory')
->addArgument(new Reference('settings'))
->addMethodCall('setContainer', array(new Reference('service_container')));
$container
->register('queue.database', 'Drupal\Core\Queue\QueueDatabaseFactory')
->addArgument(new Reference('database'));
$container->register('path.alias_manager', 'Drupal\Core\Path\AliasManager')
->addArgument(new Reference('database'))
->addArgument(new Reference('keyvalue'));
......
......@@ -18,7 +18,7 @@
* Stale items from failed batches are cleaned from the {queue} table on cron
* using the 'created' date.
*/
class Batch extends System {
class Batch extends DatabaseQueue {
/**
* Overrides Drupal\Core\Queue\System::claimItem().
......
......@@ -2,15 +2,18 @@
/**
* @file
* Definition of Drupal\Core\Queue\System.
* Contains \Drupal\Core\Queue\DatabaseQueue.
*/
namespace Drupal\Core\Queue;
use Drupal\Core\Database\Connection;
/**
* Default queue implementation.
*/
class System implements ReliableQueueInterface {
class DatabaseQueue implements ReliableQueueInterface {
/**
* The name of the queue this instance is working with.
*
......@@ -19,22 +22,30 @@ class System implements ReliableQueueInterface {
protected $name;
/**
* Constructs a System object.
* The database connection.
*
* @var \Drupal\Core\Database\Connection $connection
*/
protected $connection;
/**
* Constructs this factory object.
*
* @param string $name
* An arbitrary string. The name of the queue to work with.
* The name of the queue.
* @param \Drupal\Core\Database\Connection $connection
* The Connection object containing the key-value tables.
*/
public function __construct($name) {
function __construct($name, Connection $connection) {
$this->name = $name;
$this->connection = $connection;
}
/**
* Implements Drupal\Core\Queue\QueueInterface::createItem().
*/
public function createItem($data) {
// During a Drupal 6.x to 8.x update, drupal_get_schema() does not contain
// the queue table yet, so we cannot rely on drupal_write_record().
$query = db_insert('queue')
$query = $this->connection->insert('queue')
->fields(array(
'name' => $this->name,
'data' => serialize($data),
......@@ -49,7 +60,7 @@ public function createItem($data) {
* Implements Drupal\Core\Queue\QueueInterface::numberOfItems().
*/
public function numberOfItems() {
return db_query('SELECT COUNT(item_id) FROM {queue} WHERE name = :name', array(':name' => $this->name))->fetchField();
return $this->connection->query('SELECT COUNT(item_id) FROM {queue} WHERE name = :name', array(':name' => $this->name))->fetchField();
}
/**
......@@ -61,7 +72,7 @@ public function claimItem($lease_time = 30) {
// until an item is successfully claimed or we are reasonably sure there
// are no unclaimed items left.
while (TRUE) {
$item = db_query_range('SELECT data, item_id FROM {queue} q WHERE expire = 0 AND name = :name ORDER BY created ASC', 0, 1, array(':name' => $this->name))->fetchObject();
$item = $this->connection->queryRange('SELECT data, item_id FROM {queue} q WHERE expire = 0 AND name = :name ORDER BY created ASC', 0, 1, array(':name' => $this->name))->fetchObject();
if ($item) {
// Try to update the item. Only one thread can succeed in UPDATEing the
// same row. We cannot rely on REQUEST_TIME because items might be
......@@ -69,7 +80,7 @@ public function claimItem($lease_time = 30) {
// continue to use REQUEST_TIME instead of the current time(), we steal
// time from the lease, and will tend to reset items before the lease
// should really expire.
$update = db_update('queue')
$update = $this->connection->update('queue')
->fields(array(
'expire' => time() + $lease_time,
))
......@@ -92,7 +103,7 @@ public function claimItem($lease_time = 30) {
* Implements Drupal\Core\Queue\QueueInterface::releaseItem().
*/
public function releaseItem($item) {
$update = db_update('queue')
$update = $this->connection->update('queue')
->fields(array(
'expire' => 0,
))
......@@ -104,7 +115,7 @@ public function releaseItem($item) {
* Implements Drupal\Core\Queue\QueueInterface::deleteItem().
*/
public function deleteItem($item) {
db_delete('queue')
$this->connection->delete('queue')
->condition('item_id', $item->item_id)
->execute();
}
......@@ -122,7 +133,7 @@ public function createQueue() {
* Implements Drupal\Core\Queue\QueueInterface::deleteQueue().
*/
public function deleteQueue() {
db_delete('queue')
$this->connection->delete('queue')
->condition('name', $this->name)
->execute();
}
......
<?php
/**
* @file
* Contains \Drupal\Core\Queue\QueueDatabaseFactory.
*/
namespace Drupal\Core\Queue;
use Drupal\Core\Database\Connection;
/**
* Defines the key/value store factory for the database backend.
*/
class QueueDatabaseFactory {
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection $connection
*/
protected $connection;
/**
* Constructs this factory object.
*
* @param \Drupal\Core\Database\Connection $connection
* The Connection object containing the key-value tables.
*/
function __construct(Connection $connection) {
$this->connection = $connection;
}
/**
* Constructs a new queue object for a given name.
*
* @param string $name
* The name of the collection holding key and value pairs.
* @param \Drupal\Core\Database\Connection $connection
* The connection to run against.
*
* @return \Drupal\Core\QueueStore\DatabaseStorage
* A key/value store implementation for the given $collection.
*/
public function get($name) {
return new DatabaseQueue($name, $this->connection);
}
}
<?php
/**
* @file
* Contains \Drupal\Core\Queue\QueueFactory.
*/
namespace Drupal\Core\Queue;
use Drupal\Component\Utility\Settings;
use Symfony\Component\DependencyInjection\ContainerAware;
/**
* Defines the queue factory.
*/
class QueueFactory extends ContainerAware {
/**
* Instantiated queues, keyed by name.
*
* @var array
*/
protected $queues = array();
/**
* The settings object.
*
* @var \Drupal\Component\Utility\Settings
*/
protected $settings;
/**
* Constructs a queue factory.
*/
function __construct(Settings $settings) {
$this->settings = $settings;
}
/**
* Constructs a new queue.
*
* @param string $name
* The name of the queue to work with.
* @param bool $reliable
* (optional) TRUE if the ordering of items and guaranteeing every item executes at
* least once is important, FALSE if scalability is the main concern. Defaults
* to FALSE.
*
* @return \Drupal\Core\QueueStore\QueueInterface
* A queue implementation for the given name.
*/
public function get($name, $reliable = FALSE) {
if (!isset($this->queues[$name])) {
// If it is a reliable queue, check the specific settings first.
if ($reliable) {
$service_name = $this->settings->get('queue_reliable_service_' . $name);
}
// If no reliable queue was defined, check the service and global
// settings, fall back to queue.database.
if (empty($service_name)) {
$service_name = $this->settings->get('queue_service_' . $name, $this->settings->get('queue_default', 'queue.database'));
}
$this->queues[$name] = $this->container->get($service_name)->get($name);
}
return $this->queues[$name];
}
}
......@@ -7,14 +7,23 @@
namespace Drupal\system\Tests\Queue;
use Drupal\Core\Database\Database;
use Drupal\Core\Queue\DatabaseQueue;
use Drupal\Core\Queue\Memory;
use Drupal\Core\Queue\System;
use Drupal\simpletest\WebTestBase;
use Drupal\simpletest\DrupalUnitTestBase;
/**
* Tests the basic queue functionality.
*/
class QueueTest extends WebTestBase {
class QueueTest extends DrupalUnitTestBase {
/**
* The modules to enable.
*
* @var array
*/
public static $modules = array('system');
public static function getInfo() {
return array(
'name' => 'Queue functionality',
......@@ -27,10 +36,11 @@ public static function getInfo() {
* Tests the System queue.
*/
public function testSystemQueue() {
$this->installSchema('system', 'queue');
// Create two queues.
$queue1 = new System($this->randomName());
$queue1 = new DatabaseQueue($this->randomName(), Database::getConnection());
$queue1->createQueue();
$queue2 = new System($this->randomName());
$queue2 = new DatabaseQueue($this->randomName(), Database::getConnection());
$queue2->createQueue();
$this->queueTest($queue1, $queue2);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment