Using the sandbox batch functionality in hook_update_N does not show a progress bar in the console output

Created on 23 December 2022, almost 2 years ago
Updated 21 January 2023, almost 2 years ago

Problem/Motivation

I have a very large dataset containing over 500.000+ entities (most of them with 50+ fields). I need to modify this dataset and wrote a update hook (which in my case deletes a chunk of deprecated data). Due to the large volume, I want to use the batch system in the sandbox to make sure PHP will not get any timeout / out of memory issues. I can confirm that in my update hook below the entities are indeed being processed in a batch, however NO output is shown in the console until AFTER the update is finished. I want to be able to see how far my update is and was expecting (like any other batch system functionality) to see a progress bar or status messages in my console. I've also noticed you will not see the Drupal messenger messages (till after the update is finished) and it is also not possible to force output to the console myself by using the ConsoleOutput class from Symfony. Am I doing something wrong here, or is this a bug in Drupal core?

/**
 * Remove imported Destiny insurances.
 */
function cml_insurance_update_8108(&$sandbox) {
  $accountSwitcher = \Drupal::service('account_switcher');
  $user = \Drupal::entityTypeManager()->getStorage('user')->load(1);
  $accountSwitcher->switchTo($user);
  $entityStorage = \Drupal::entityTypeManager()->getStorage('insurance');

  // Get max.
  if (!isset($sandbox['max'])) {
    $query = $entityStorage->getQuery();
    $query->accessCheck(FALSE);
    $query->exists('destiny_id');
    if (!$max = $query->execute()) {
      \Drupal::messenger()->addMessage('No entities were found to process. Finishing update.');
      $sandbox['#finished'] = 1;
      return;
    }

    $sandbox['progress'] = 0;
    $sandbox['max'] = count($max);
    \Drupal::messenger()->addMessage('A total of ' . count($max) .  ' entities were found to process. Starting update.');
  }

  // Get batch of entity ids.
  $query = $entityStorage->getQuery();
  $query->accessCheck(FALSE);
  $query->range($sandbox['progress'], 100);
  $entityIds = $query->execute();

  if (empty($entityIds)) {
    \Drupal::messenger()->addMessage('No entities left to process. Finishing update.');
    $sandbox['#finished'] = 1;
    return;
  }

  // Delete entities.
  foreach ($entityIds as $entityId) {
    /** @var \Drupal\cml_insurance\Entity\InsuranceInterface $entity */
    $entity = $entityStorage->load($entityId);

    // Delete referenced entities.
    if ($reference = $entity->getRelation()) {
      $reference->delete();
    }

    $entity->delete();
    $sandbox['progress']++;
  }

  // Set message output.
  \Drupal::messenger()->addMessage($sandbox['progress'] . ' amount of entities have been processed.');

  if ($sandbox['progress'] >= $sandbox['max']) {
    $sandbox['#finished'] = 1;
    return;
  }

  $sandbox['#finished'] = ($sandbox['progress'] / $sandbox['max']);
  $accountSwitcher->switchBack();
}
💬 Support request
Status

Closed: outdated

Version

9.4

Component
Batch 

Last updated 4 days ago

Created by

🇳🇱Netherlands kevin.brocatus

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.

Production build 0.71.5 2024