Problem/Motivation

The Batch API provides a progress bar that could potentially be used not only for a queue of actions but also to indicate a long asynchronous operation on the backend by checking its status.

Currently, this can be achieved using `sleep()` in the batch action callback. However, this is not an ideal solution for performance. While a sleeping PHP process does not use CPU resources, it still maintains an active connection and occupies both the web server worker and the PHP-FPM worker for the entire duration.

The best approach would be to enable the UI to send short requests with a configurable delay. While `core/drupal.progress` supports a delay, `core/drupal.batch` always sets it to 10. Additionally, some jobs require executing only one operation per request.

Some abstract example:

  // In form submit:
  shell_exec("$long_command > $filename 2>/dev/null &");

  // Send 1 request per second to BE.
  $batch_builder = (new BatchBuilder())
      ->setTitle($this->t('Please wait'))
      ->setDelay(1000);

  $batch_builder->addOperation('my_module_check_exec_status', [$filename]);
  $batch_builder->addOperation('my_module_process_file', [$filename]);

  batch_set($batch_builder->toArray());
function my_module_check_exec_status($filename, array &$context) {
    if (!isset($context['sandbox']['finished'])) {
      $context['sandbox']['finished'] = 0;
    }
    $context['sandbox']['finished']++;

    if (file_exists($filename)) {
      $context['finished'] = 1;
    } else {
      $context['finished'] = min($context['sandbox']['finished']/100, .99);
    }
}

Proposed resolution

Add a "delay" property to the batch definition, which would be passed to the progress bar and allow only one operation per request. This appears to be a straightforward change — see the example provided in the MR.

Remaining tasks

- Tests
- Non-progressive batch exception or `sleep()` implementation (needs discussion)

User interface changes

No

API changes

`batch_set`:

 *   - delay: A number of milliseconds between operations. Sets browser's
 *     progress bar delay, only one operation would be performed per request
 *     if positive value provided.

`BatchBuilder`

  /**
   * Sets delay in milliseconds between operations for a progressive batch.
   *
   * Doesn't affect non-progressive batch.
   *
   * @param int $delay
   *   (optional) Delay in milliseconds between operations. Sets browser's
   *   progress bar delay, only one operation would be performed per request
   *   if positive value provided. Resets value to default (0) if the param
   *   is not provided.
   *
   * @return $this
   */
  public function setDelay($delay = 0) {
    $this->delay = $delay;
    return $this;
  }

Issue fork drupal-3553008

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

dewalt created an issue. See original summary.

dewalt’s picture

The patch to safely use with composer

dewalt’s picture

Issue summary: View changes
dewalt’s picture

Issue summary: View changes
dewalt’s picture

Issue summary: View changes
dewalt’s picture

StatusFileSize
new5.35 KB

Added non-progressive batch support, updating the patch too.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.