API for handling unique queue items

Created on 26 April 2012, almost 13 years ago
Updated 27 February 2024, about 1 year ago

Re-start for this after #1492188: Update module creates duplicate queue items β†’ drifted back to being a workaround fix for update.module.

Right now, update.module does it's own unique checks based on cache entries in cache_update. This should be a feature provided by the queue system itself, either by providing an actual unique queue or by providing wrapper functions to deal with this.

API suggestion by @beejebus:

function drupal_unique_queue_item_create(QueueInterface $queue, $data, $key) {
  $status = db_merge('unique_queue_item')
    ->key(array('key' => $key))
    ->insertFields(array(
      'created' => REQUEST_TIME,
    ))
    ->updateFields(array(
      'updated' => REQUEST_TIME,
    ))
    ->execute();
  if ($status === DrupalCoreDatabaseMerge::STATUS_INSERT) {
    $queue->createItem($data);
  }
}

This is also relevant for #1547008: Replace Update's cache system with the (expirable) key value store β†’ which aims to re-unite update.module with the cache API, which is not possible right now due to these fetch_task entries. Not sure if it's the right approach though, maybe yet another API for the project information data might make more sense for that. But that isn't possible either until we this API here.

πŸ“Œ Task
Status

Active

Version

11.0 πŸ”₯

Component
BaseΒ  β†’

Last updated about 2 hours ago

Created by

πŸ‡¨πŸ‡­Switzerland berdir Switzerland

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • namespace Drupal\my_class\Queue;
    
    use Drupal\Core\Queue\DatabaseQueue;
    
    /**
     * Custom queue implementation to merge on creation, preventing duplicates.
     *
     * @ingroup queue
     */
    class MergeDatabaseQueue extends DatabaseQueue {
    
      /**
       * {@inheritdoc}
       */
      protected function doCreateItem($data): ?int {
        // This is copied and modified from DatabaseQueue::doCreateItem().
        // Merge instead of insert to prevent duplicates. An item is updated if it
        // already exists.
        $serialized = serialize($data);
        $query = $this->connection->merge(static::TABLE_NAME)
          ->keys([
            'name' => $this->name,
            'data' => $serialized,
          ])
          ->fields([
            'name' => $this->name,
            'data' => $serialized,
            // Note that this will update the 'created' field for an existing item.
            // We cannot rely on REQUEST_TIME because many items might be created
            // by a single request which takes longer than 1 second.
            'created' => \Drupal::time()->getCurrentTime(),
          ]);
        return $query->execute();
      }
    
    }
    
  • πŸ‡ΊπŸ‡ΈUnited States pwolanin

    the queue_unique contrib module already handles this - it ignores a new queue item if there is an existing one with the same data (or really the same sha256 of the serialized data)

    https://www.drupal.org/project/queue_unique β†’

  • πŸ‡³πŸ‡΄Norway steinmb

    It is simple module, but as now, it lack maintenance, so perhaps adopting it to core would be good thing? The uniqueness support should be useful in core. We currently we roll custom code making sure we do not queue identical items coming from an external RabbitMQ system.

  • I agree. This functionality should be in Core.

  • πŸ‡ΊπŸ‡ΈUnited States pwolanin

    I'll see if they will add me as a maintainer there, but it's simple enough we could likely merge into core

  • πŸ‡ΊπŸ‡ΈUnited States pwolanin

    ok, also sounds like moving queue_unique into core is something that could be accepted, so we just need to make a MR here

  • πŸ‡¬πŸ‡§United Kingdom catch

    I can't remember exactly what we ended up doing for update module, but pretty sure nothing much changed since 2012 so we could probably still convert it to this API once it's available.

Production build 0.71.5 2024