3

While inserting items in a Queue how can I check if the item I am trying to insert is already present in the Queue?

4 Answers 4

6

The queue API doesn't have a method for this. It is very limited on purpose, as some queue systems might not be able to provide information like this.

The update module has its own wrapper to do this, by additionally storing all the task names in key value as well. See \Drupal\update\UpdateProcessor::createFetchTask:

public function createFetchTask($project) {
  if (empty($this->fetchTasks)) {
    $this->fetchTasks = $this->fetchTaskStore->getAll();
  }
  if (empty($this->fetchTasks[$project['name']])) {
    $this->fetchQueue->createItem($project);
    $this->fetchTaskStore->set($project['name'], $project);
    $this->fetchTasks[$project['name']] = REQUEST_TIME;
  }
}
3

Add this function:

/**
 * Adding item to queue.
 *
 * @param string $queue_id
 *   The name of the queue to work with.
 * @param array $item_data
 *   Arbitrary data to be associated with the new task in the queue.
 * @param bool $find_identical
 *   Checking exist item in the queue or not.
 *   If exists, new item wouldn't be added in queue.
 */
function MY_MODULE_add_to_queue($queue_id, array $item_data, $find_identical = FALSE) {
  $queue_item_exists = FALSE;

  if ($find_identical) {
    $query = \Drupal::database()->select('queue', 'q');
    $query->condition('name', $queue_id);
    $query->condition('data', serialize($item_data));
    $query->condition('expire', 0);
    $query->fields('q', ['item_id']);

    $queue_item_exists = !empty($query->execute()->fetchAll());
  }

  if (!$queue_item_exists) {
    \Drupal::queue($queue_id)->createItem($item_data);
  }
}

And in place where you adding new items in queue use this:

MY_MODULE_add_to_queue('YOUR_QUEUE_WORKER', $item_to_add, TRUE);
2

It depends on how your implementation. How do you define uniqueness? By a duplicate queue item object (e.g. all properties are equal), by a specific property on your queue item object, or something else?

The Queue interfaces QueueInterface & ReliableQueueInterface don't define any method for uniqueness. It's up to you to define what unique means and to enforce it when using the createItem() method.

To have a concrete example, take a look at the Queue Unique project (it's D7 but the premise is the same this has releases for D7 and D8/D9 now). It's creating it's own implementation of DrupalQueueInterface (QueueInterface in D8) and adding a table where it MD5ing a serialized queue object to determine if an item is unique (if the MD5 hash of the serialized object is the same, it's a duplicate which is rejected).

1

Here you can find a nice D7 solution: https://www.webomelette.com/overriding-queues-drupal-7-or-how-not-create-duplicate-queue-items

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.