My module does some tasks via Batch API. To avoid duplicating code, I want to do those same tasks during a cron run by programmatically starting and executing the batch without trying to redirect the user to the standard batch job progress bar thingie. There seems to be the facility for this by setting the 'progressive' value of the $process_info array to FALSE, but by the same token, there doesn't seem to be a way to do that - it's hard-coded to TRUE . From D6's form.inc (D7's version is the same in this regard):
function batch_process($redirect = NULL, $url = NULL) {
$batch =& batch_get();
if (isset($batch)) {
// Add process information
$url = isset($url) ? $url : 'batch';
$process_info = array(
'current_set' => 0,
'progressive' => TRUE, // <= HERE
'url' => isset($url) ? $url : 'batch',
'source_page' => $_GET['q'],
'redirect' => $redirect,
);
$batch += $process_info;
if ($batch['progressive']) {
// Clear the way for the drupal_goto redirection to the batch processing
// page, by saving and unsetting the 'destination' if any, on both places
// drupal_goto looks for it.
// […snip…]
drupal_goto($batch['url'], 'op=start&id='. $batch['id']);
}
else {
// Non-progressive execution: bypass the whole progressbar workflow
// and execute the batch in one pass.
require_once './includes/batch.inc';
_batch_process();
}
}
}
Unless I'm missing something, this means that, though the functionality exists to do what I want to do, it's not actually possible to do so without hacking core - the code in that "else" branch will never, ever execute. One dead kitten later, I get the expected result.
However, I will allow that I'm just misunderstanding how to use an esoteric feature of this esoteric API and that doing what I need to do is possible without slaughtering kittens; in which case, a bit of edumacation would be appreciated.
Comment | File | Size | Author |
---|---|---|---|
#47 | cli-batch-638712-47.patch | 6.5 KB | Tim Bozeman |
#41 | interdiff.txt | 1.58 KB | Cameron Tod |
#41 | core-batch-638712-41.patch | 1.38 KB | Cameron Tod |
#40 | core-batch-638712-40.patch | 1.42 KB | Cameron Tod |
#39 | core-batch-638712-39.patch | 1.42 KB | jouri |
Issue fork drupal-638712
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 #1
yched CreditAttribution: yched commentedYes, it's an API overlook :-(.
You can do that with:
before calling batch_process().
Comment #2
Garrett Albright CreditAttribution: Garrett Albright commentedThat works. Thank you. (Is there any documentation somewhere on that =& operator? I think I get what it does by peeking at the code, but I'd like to see it written down somewhere. Unfortunately, it's impossible to search for "=&" in Yahoo, Google or PHP.net's built-in search engine, and a quick glance of the "Operators" section of the PHP.net docs wasn't profitable.)
So how can we fix this? Perhaps add a new ['progressive'] key to the array passed to batch_set() which gets passed along to the $batch['progressive'] value in batch_process()… ugh. If any of the sets have a FALSE ['progressive'] key, the batch won't be run as progressive…? The attached patch should implement that, as well as cleaning up the docs in the D6 version and removing mention of a fictitious batch_init() from both versions. If this counts as an API change and is therefore unable to be committed, please at least commit the documentation correction patches.
Comment #3
yched CreditAttribution: yched commentedThat would rather be a parameter for batch_process(), IMO.
Doc cleanup patches are good to go. Oops for batch_init(), that function was refactored out even before Batch API landed in D6...
Could you post the isolated patch for D7 ?
Comment #4
Garrett Albright CreditAttribution: Garrett Albright commentedWhat do you mean by "isolated?" Do you mean just the progressive tweak without the batch_init() removal from the comments? If so, here you go.
It being a parameter for batch_process() makes sense too, but the D6 version already has two parameters, and the D7 version has three…
Comment #5
yched CreditAttribution: yched commentedSorry, I meant just batch_api_docs_cleanup-D7.patch so we can set this to RTBC and backport asap.
The 'progressive' thing still needs some thinking IMO, + I'd prefer to wait for #629794: Scaling issues with batch API to land ;-)
Comment #6
Dave ReidWow just ran into this trying to run a batch process from drush, which is impossible without this bug/hack. Patch in #4 worked for me.
Comment #7
Dave ReidThis will need a backport to D6 as well.
Comment #8
yched CreditAttribution: yched commentedPlz see my #3 / #5
Comment #9
Dries CreditAttribution: Dries commentedIs there any down-sides to setting this parameter? The documentation makes it read as if it is a UI-thing only.
Comment #10
Dave ReidNot that I can tell. Being able to set a batch as not progressive allows us to run it in the command line and Drush.
Comment #11
Garrett Albright CreditAttribution: Garrett Albright commented…and during a cron run, which was my goal. Not that that is necessarily the right answer to my problem, but it works.
Comment #12
yched CreditAttribution: yched commentedre Dries #9
Batch "API" is mainly two functions:
- batch_set(): define a set of batched operations to be run by the batch engine. Several independent code branches can their own add batched ops (for instance several form submit handlers defined in different modules).
- batch_process(): launch the execution of the batch sets that were defined earlier during the page request. Batch sets are executed sequentially and stay independent the whole time.
Saying whether processing should happen through the progressbar UI or some other iteration mechanism or just 'in one pass' is something for batch_process()
- it will affect the whole processing, so what if set A specifies 'progressive' and batch B specifies 'non progressive' ?
- it's the caller of batch_process() who knows its own context (form submission, page callback -> UI OK, programmatic form, cron, drush -> UI not OK) and therefore has the elements to decide if execution should be progressive or not. In the generic case, callers of batch_set() have no clue, an it should not matter to them anyway.
- for this exact reason, it's batch_process() that received the option to specify a custom 'iterator' ($redirect_callback) in #555762: Changes to batch API
Adding the 'progressive' option on batch_set() as the patch does is conceptually wrong, it's only 'easier' in terms of API changes (because it adds an optional property inside the $batch_set array param)
I'd much rather have us add the option on batch_process(). 2 options:
1 - light change: 4th optional parameter for batch_process() - no API break
2 - clean and future proof change: rework the current arguments of batch_process() into a single $options array. Note that most batches in contrib are set in form submits, and so should not be affected by the change since i this case Form API takes care of the batch_process() call.
Of course I strongly favor the latter, but that would need a green light for the API break.
Comment #13
Garrett Albright CreditAttribution: Garrett Albright commentedOkay, I think Dave and I interpreted the question differently than yched, but I have to say I agree with yched's post conceptually - doing it via batch_process() would probably be smartest. However, my interpretation of the code already in place was that it was intended that that would be something set with batch_set(), so that's the path I took with my patch.
I say we make a patch which satisfies option 1 for now. In the chance we get the green light to break API, we can adapt it to option 2 - and then pile on patches to unbreak update.php and such. This isn't something I can tackle at the moment; yched, Dave, could either of you take this on?
Comment #14
yched CreditAttribution: yched commentedAttached patch does the lightest approach (#12 option 1). API addition, no API break.
Hackish, though[edit: hackish is not the word, let's say that's a kind of a param soup]I think the clean version is something like: batch_process($options)
Supported options:
- iteration_callback (current $redirect_callback param): the iteration method. Defaults to 'drupal_goto', FALSE means not progressive.
- process_url (current $url param): page that holds the progress bar. Defaults to '\batch'. Only used if 'iteration_callback' == 'drupal_goto'.
- redirect_url (current $redirect param): page to redirect after processing. Defaults to the 'redirect' property of the last processed set. Only used if 'iteration_callback' == 'drupal_goto'.
I can try to work on that approach if the API change is validated.
Meanwhile, CNR for the 'code-freeze friendly' patch.
Comment #15
yched CreditAttribution: yched commenteder, patch.
Comment #16
moshe weitzman CreditAttribution: moshe weitzman commentedsubscribe since drush updatedb will need changes when this lands.
Comment #19
nonsieSubscribe
Comment #20
moshe weitzman CreditAttribution: moshe weitzman commentedsmall, helpful patch.
Comment #21
Dave ReidStill not the easiest to call batch_process() if you want a non-progressive run. The first three settings don't matter if the fourth is FALSE. Would it be too much to ask if we move the progressive parameter first?
Comment #22
Garrett Albright CreditAttribution: Garrett Albright commentedI would imagine that would break everything which currently uses Batch API. At that point, we might as well get rid of the mile-long list of parameters approach and go with the parameters-in-an-array approach, 'cuz that's going to break everything too.
Comment #23
webchickChecking to see if this still applies now that the scalable batch API patch landed.
Comment #26
aspilicious CreditAttribution: aspilicious commentedI am trying to reroll this...
1) tried to apply on latest head, check
2) tried to install with changes check
So all this needs is a proper review if the bot is happy
Comment #27
q0rban CreditAttribution: q0rban commentedSubscribe
Comment #28
retester2010 CreditAttribution: retester2010 commented#26: batch-progressive-638712-26.patch queued for re-testing.
Comment #30
Dave ReidLet's try this instead. Let's make it a non-progressive batch if the $redirect_callback parameter is FALSE.
Comment #31
bleen CreditAttribution: bleen commentedsubscribing
Comment #32
btopro CreditAttribution: btopro commentedsub... kind of a major issue for trying to reuse batch processes as background jobs on server..
Comment #33
markj CreditAttribution: markj commentedSubscribing.... Dave's patch passed tests 3.5 years ago.
Comment #34
RoSk0Reroll
Comment #35
RoSk0Comment #36
texas-bronius CreditAttribution: texas-bronius commentedSeems to work for me:
I'd really been poking at this from every other conceivable angle -- so glad to have come across this thread. I think I understand why we are putting the burden of determining progressive mode on batch_process() and not a param
'progressive' => FALSE
on $batch on batch_set($batch). So what seems to be working (with this third-parameter-truthiness patch) for me is:See PHP docs for php_sapi_name().
Comment #37
jouri CreditAttribution: jouri at TUI commentedIn Drupal 8 it's not possible to do a non progressive batch through cli because there's always a route match needed.
I fixed this in the attached patch.
Comment #39
jouri CreditAttribution: jouri at TUI commentedForgot the html subfolder, removed it.
Comment #40
Cameron Tod CreditAttribution: Cameron Tod at Acquia commentedLatest patch is against 8.0.x - bumping version though I'm not sure on which branch this should go in.
Have rerolled patch to remove preceding 'html' directory.
Comment #41
Cameron Tod CreditAttribution: Cameron Tod at Acquia commentedUpdated the comment and param name, I think this construction is a bit more readable. Re #36, It does feel a bit weird to be disabling progressive batching via setting the source_url rather than setting
$batch['progressive']
directly.Comment #43
jonathanshawLooks like a feature request rather than an outright bug?
Comment #47
Tim Bozeman CreditAttribution: Tim Bozeman at CyberSolution for Achieve Internet commentedOld issue, but it seems to have resurfaced.
Progressive = TRUE is hard coded in form.inc batch_process(). Here's a fresh patch. It's only a minor tweak, but the indentation is different so it changed a bunch of lines...
With the patch, you can run a cron or cli batch job like this:
Comment #48
borisson_I like that this makes the code little less indented and adds early returns.
I don't like that this uses $_SESSION instead of the symfony's session storage.
In any case, we need to add a test that fails without this patch attached.
Comment #51
whereisaaron CreditAttribution: whereisaaron as a volunteer commentedGlad I ran into this thread for the required hack.
But 10 years and multiple passing patches and simple as three line to add the missing option, but still nothing applied to fixed this hard-coding bug, not to D6 or D7 or D8?
Comment #53
handkerchiefAny news on that?
Comment #54
borisson_I'm pretty sure we need to add tests to this and we can get this in after that. Asking for someone else to do that will not make that go quicker.
I'm also not sure about the last patch (#47) over #41. It is 5 times as big and does a lot of unrelated work. I really like that direction because it makes the code better but it is harder to see what really needed to change. We can do the refactor in a followup instead.
So if #41 still applies (and fixes the issue) - I think that is a good place to start, all we would need added on top of that is the test :)
Comment #55
batkorsubscribe
Comment #56
handkerchiefOk #1 was my solution. Simple.