Quantcast
Channel: Issues for Drupal core
Viewing all articles
Browse latest Browse all 294800

Adding a new batch set while the batch is running breaks batch order

$
0
0

Problem/Motivation

1. Define 3 batches with operations.
2. batch_set($batch_0);
3. batch_process();
4. During the processing of the first batch two new batches are being added through batch_set.
5. Because there is an active batch the new batch being added will be not placed at the end but prepended to the batch set stack right after the current active batch, but the operations of the other batches, that are already in the db queue will not be reordered. The batch set list will look now like this - $batch_0, $batch_1, $batch_2, but the queued operations will look like this - drupal_batch:49:0 (batch 0), drupal_batch:49:1 (batch 1), drupal_batch:49:1 (batch 2). This leads to having the batch set stack like 0-1-2, but the operations are queued in the wrong order - 0-2-1.

A current example in core is when installing a new module in hook_update_N:
1.DbUpdateController::triggerBatch() starts the processing of the updates in a batch.
2. During the updates a module is being installed.
3. The installation of a module triggers locale_system_update(), which on its turn will call batch_set() twice.
4. The second batch set from locale_system_update() depends on the first batch set from the same function.
5. The problems starts with the second call to batch_set() in locale_system_update().
6. What has happened now is the following:
6.1. The second batch set from locale_system_update() is put in front of the first batch set from locale_system_update(), which means it will be processed before the first one - wrong, because it depends on the first one and the first one should be executed before the second one.
6.2. The operations from the second batch set from locale_system_update() are being put together into the same queue of the first batch set from locale_system_update(), because the indexes of the batch set stack are the ones being used to determine the queue name and prepending the second batch set and reordering the indexes breaks all the corresponding queue mapping leading to executing operations in a batch set, which do not belong to that batch set.
7. In this case we notice the problem by having warning that the functions locale_translation_batch_status_check(), locale_translation_batch_fetch_download() and locale_translation_batch_fetch_import() could not be found. We see these warnings because the operations are being processed as part of the wrong batch set and not the correct $batch['file'] is being included! The warnings:

call_user_func_array() expects parameter 1 to be a valid callback, function 'locale_translation_batch_status_check' not found or invalid function name          [warning]
batch.inc:163
call_user_func_array() expects parameter 1 to be a valid callback, function 'locale_translation_batch_fetch_download' not found or invalid function name        [warning]
batch.inc:163
call_user_func_array() expects parameter 1 to be a valid callback, function 'locale_translation_batch_fetch_import' not found or invalid function name          [warning]
batch.inc:163

Proposed resolution

1. Ensure that when multiple batches are being added during an active batch, that they will be put into the batch set stack before the ones that are already in the queue, but the order of the batches added during an active batch should be maintained. This means:

  1. batch_set($batch_1);
  2. batch_process();
  3. During the processing of an operation from $batch_1, batch_set() is called twice with $batch_2 and $batch_3.
  4. $batch_2 should be processed before $batch_3.

2. Ensure that when prepending and appending batch sets during an active batch the batch set queue mapping will be maintained by not breaking the indexes in the batch set stack.

Remaining tasks

User interface changes

API changes

Data model changes


Viewing all articles
Browse latest Browse all 294800

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>