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;
}
| Comment | File | Size | Author |
|---|---|---|---|
| #6 | core-batch_api_delay_option-3553008-6.patch | 5.35 KB | dewalt |
Issue fork drupal-3553008
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
Comment #2
dewalt commentedThe patch to safely use with composer
Comment #3
dewalt commentedComment #4
dewalt commentedComment #5
dewalt commentedComment #6
dewalt commentedAdded non-progressive batch support, updating the patch too.