Problem/Motivation

Core added Drupal\Core\Queue\DelayableQueueInterface in Drupal 9.1.0, with #3116478: Add a way to silently keep an item locked when processing a queue via cron. Its single method, delayItem($item, int $delay), sets the expiry of the current claim on an item to the current time plus $delay seconds. The item stays claimed until then, and becomes available again after that.

Core's DatabaseQueue implements it, and Drupal\Core\Cron uses it: when a queue worker throws DelayedRequeueException, cron calls delayItem() with the delay from the exception if the queue implements the interface. Otherwise, cron leaves the item's current claim alone, so the item becomes available again when its original claim expires. No item is lost; only the delay requested by the worker is ignored.

The mongodb_storage queue was written in #3130220: Implement the queue service before the interface existed, and does not implement it.

Most contrib queue backends do not implement it either. This comparison covers the default development branch of each project, as found in its code on 2026-09-30:

Project, branch, class Declares Drupal 10/11 DelayableQueueInterface releaseItem() on an item that is not claimed
core DatabaseQueue, Batch yes yes TRUE
core Memory, BatchMemory yes no FALSE
mongodb 8.x-2.x Queue yes no FALSE
mongodb 3.x: core DatabaseQueue on the MongoDB database driver, with a core patch adapting its queries Drupal 11.1 only yes, core's TRUE: the driver's updates return the matched count
redis 2.x RedisQueue, ReliableRedisQueue yes no TRUE
redis 8.x-1.x, all queue classes yes no no return value (NULL)
rabbitmq 4.x Queue Drupal 10 only no throws an Error
kafka 8.x-1.x KafkaQueue yes no TRUE
queue_unique 8.x-2.x UniqueDatabaseQueue no (Drupal 8/9) yes, inherited from DatabaseQueue TRUE, inherited
aws_sqs 8.x-1.x AwsSqsQueue no (Drupal 8/9) no depends on the AWS response
aws_sqs_api 1.0.x AwsSqsQueue no (Drupal 9) no no return value (NULL)
beanstalkd 8.x-1.x BeanstalkdQueue no (Drupal 8) no no return value (NULL)
openstack_queues 8.x-1.x OpenstackQueue no (Drupal 8) no FALSE
advancedqueue 8.x-1.x, own backend API instead of QueueInterface yes not applicable: every backend must accept a delay in enqueueJob() and retryJob() not applicable: releasing is the optional SupportsReleasingJobsInterface::releaseJob()

Advanced Queue is the exception in design rather than in interface: it does not implement QueueInterface, but its own backend API makes delays mandatory, and its processor retries failed jobs after a delay, which is what delayItem() provides for core queues.

So among the compared backends not built on core's DatabaseQueue, none implements the interface. The last column shows that behavior also varies where the core interface leaves room, which this plan should keep in mind when deciding how closely to follow core.

Proposed resolution

Evaluate whether the MongoDB queue should implement DelayableQueueInterface, then either:

  • create a feature request to implement it, or
  • document in docs/modules/mongodb_storage.md that the queue does not implement it, why, and what happens instead when a worker throws DelayedRequeueException.

Points to evaluate:

  • Use: which core and contrib queue workers throw DelayedRequeueException, and how often sites would run such workers on a MongoDB queue.
  • Cost: the queue already stores the claim expiry in expires, and claimItem() already treats items with an expired claim as available, so delayItem() would be a single update of expires, like releaseItem(). Tests could follow core's CronQueueTest::testDelayedRequeue().
  • Compatibility: whether a MongoDB queue meant as a replacement for core's DatabaseQueue should support what it supports, given that other backends do not.
  • Interaction with #3626957: Implement or document ReliableQueue support or lack thereof: whether delaying items affects the ordering guarantees evaluated there.

Remaining tasks

  • Evaluate the points above.
  • Decide, and record the decision in this issue.
  • Either create the feature request, or update the documentation.

User interface changes

None.

API changes

None in this plan. A resulting feature request would make Queue also implement DelayableQueueInterface, an addition that does not break callers.

Data model changes

None.

AI disclosure

Issue created with AI asssitance.

Comments

fgm created an issue. See original summary.

fgm’s picture