The batch processed all the items, but instead of showing the finish message, I see the error "Allowed memory size of 536870912 bytes exhausted".
When I debug the code, I notice that Drupal loads each proccessed block on batch finish (ContentEntityBase->__construct
). I can't figure out why Drupal is doing that.
Structure of the code:
This is a custom module with form class, and batch functions in the custom_module.module
file. On form submit, the module calls the create batch function:
public function submitForm(array &$form, FormStateInterface $form_state) {
custom_module_make_batch();
}
The custom_module_build_batch function getting ids of custom blocks (4000 or more) and generating the batch:
function custom_module_make_batch()
{
$batch = [];
$items = get_blocks_ids();
$batch = custom_module_generate_batch($items);
batch_set($batch);
}
function custom_module_generate_batch($items)
{
$operations = [];
$operations_groups = array_chunk($items, 50);
foreach ($operations_groups as $key => $operations_group) {
$operations[] = [
'custom_module_batch_op',
[$operations_group],
];
}
$batch = [
'operations' => $operations,
'finished' => 'custom_module_batch_finished',
'title' => 'Custom batch',
'init_message' => 'Batch is starting.',
'progress_message' => 'Processed @current out of @total parts.',
'error_message' => 'Batch has encountered an error.',
];
return $batch;
}
function custom_module_batch_op($operations_group, &$context) {
foreach ($operations_group as $key => $bid) {
$block = \Drupal::service('entity.repository')->loadEntityByUuid('block_content', $bid);
$block->field_name = $new_value;
$block->save();
}
}
function custom_module_batch_finished($success, $results, $operations)
{
$messenger = \Drupal::messenger();
if ($success) {
// Here we could do something meaningful with the results.
// We just display the number of nodes we processed...
if ($total) {
$messenger->addMessage(t('@count results processed.', ['@count' => $total]));
} else {
$messenger->addMessage(t('There no items for the migration'));
}
} else {
// An error occurred.
// $operations contains the operations that remained unprocessed.
$error_operation = reset($operations);
$messenger->addMessage(
t(
'An error occurred while processing @operation with arguments : @args',
[
'@operation' => $error_operation[0],
'@args' => print_r($error_operation[0], TRUE),
]
)
);
}
}
$new_value
is undefined. And better use$block->set('field_MYFIELD', $new_value)
to set the value or$block->set('field_MYFIELD', [])
to empty it.get_blocks_ids()
is loading all the items, which would explain the error message. A batch callback executes the query to get the necessary items. Getting all the items and handing them in batches is not how a batch operation is supposed to work, since batch operations are done to avoid to use all the available memory and avoid time outs caused from PHP taking more time to handle the request than the assigned time.