See patch for my suggested fix.

I tried to create a batch job but had a hard time getting it to work with the documentation provided. It ended up that the function I registered to run in the batch was not normally included, so I had to specify that file to be included.

I patched the documentation to show that you can define a file to be included in a batch run

Please use this patch or something similar. There are 0 errors about function not found. It just runs the batch as if everything ran without incident.

Thank you!
Mark

Comments

JirkaRybka’s picture

Another unclear point is the $context['sandbox'], which is NOT persistent in the scope of the whole batch, i.e. it's cleared after every single operation in the batch. Only when the same operation is called multiple times (which is not default), it can benefit from sandbox - otherwise the batch persistent data needs to be stored (awkwardly) in results instead.

jhodgdon’s picture

Status: Active » Needs work

Which function or api doc page are you patching? Your patch is difficult to review as it is...

markDrupal’s picture

It's the comments for the batch_set($batch_definition) function

/**
 * @defgroup batch Batch operations
 * @{
 * Functions allowing forms processing to be spread out over several page
 * requests, thus ensuring that the processing does not get interrupted
 * because of a PHP timeout, while allowing the user to receive feedback
 * on the progress of the ongoing operations.
 *
 * The API is primarily designed to integrate nicely with the Form API
 * workflow, but can also be used by non-FAPI scripts (like update.php)
 * or even simple page callbacks (which should probably be used sparingly).
 *
 * Example:
 * @code
 * $batch = array(
 *   'title' => t('Exporting'),
 *   'file' => drupal_get_path('module', 'my_module') .'/my_module.batch.inc',
 *   'operations' => array(
 *     array('my_function_1', array($account->uid, 'story')),
 *     array('my_function_2', array()),
 *   ),
 *   'finished' => 'my_finished_callback',
 * );
 * batch_set($batch);
 * // only needed if not inside a form _submit handler :
 * batch_process();
 * @endcode
 *
 * Sample batch operations:
 * @code
 * // Simple and artificial: load a node of a given type for a given user
 * function my_function_1($uid, $type, &$context) {
 *   // The $context array gathers batch context information about the execution (read),
 *   // as well as 'return values' for the current operation (write)
 *   // The following keys are provided :
 *   // 'results' (read / write): The array of results gathered so far by
 *   //   the batch processing, for the current operation to append its own.
 *   // 'message' (write): A text message displayed in the progress page.
 *   // The following keys allow for multi-step operations :
 *   // 'sandbox' (read / write): An array that can be freely used to
 *   //   store persistent data between iterations. It is recommended to
 *   //   use this instead of $_SESSION, which is unsafe if the user
 *   //   continues browsing in a separate window while the batch is processing.
 *   // 'finished' (write): A float number between 0 and 1 informing
 *   //   the processing engine of the completion level for the operation.
 *   //   1 (or no value explicitly set) means the operation is finished
 *   //   and the batch processing can continue to the next operation.
 *
 *   $node = node_load(array('uid' => $uid, 'type' => $type));
 *   $context['results'][] = $node->nid .' : '. $node->title;
 *   $context['message'] = $node->title;
 * }
 *
 * // More advanced example: multi-step operation - load all nodes, five by five
 * function my_function_2(&$context) {
 *   if (empty($context['sandbox'])) {
 *     $context['sandbox']['progress'] = 0;
 *     $context['sandbox']['current_node'] = 0;
 *     $context['sandbox']['max'] = db_result(db_query('SELECT COUNT(DISTINCT nid) FROM {node}'));
 *   }
 *   $limit = 5;
 *   $result = db_query_range("SELECT nid FROM {node} WHERE nid > %d ORDER BY nid ASC", $context['sandbox']['current_node'], 0, $limit);
 *   while ($row = db_fetch_array($result)) {
 *     $node = node_load($row['nid'], NULL, TRUE);
 *     $context['results'][] = $node->nid .' : '. $node->title;
 *     $context['sandbox']['progress']++;
 *     $context['sandbox']['current_node'] = $node->nid;
 *     $context['message'] = $node->title;
 *   }
 *   if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
 *     $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
 *   }
 * }
 * @endcode
 *
 * Sample 'finished' callback:
 * @code
 * function batch_test_finished($success, $results, $operations) {
 *   if ($success) {
 *     $message = format_plural(count($results), 'One post processed.', '@count posts processed.');
 *   }
 *   else {
 *     $message = t('Finished with an error.');
 *   }
 *   drupal_set_message($message);
 *   // Providing data for the redirected page is done through $_SESSION.
 *   foreach ($results as $result) {
 *     $items[] = t('Loaded node %title.', array('%title' => $result));
 *   }
 *   $_SESSION['my_batch_results'] = $items;
 * }
 * @endcode
 */

/**
 * Open a new batch.
 *
 * @param $batch
 *   An array defining the batch. The following keys can be used:
 *     'operations': an array of function calls to be performed.
 *        Example:
 *        @code
 *        array(
 *          array('my_function_1', array($arg1)),
 *          array('my_function_2', array($arg2_1, $arg2_2)),
 *        )
 *        @endcode
 *     All the other values below are optional.
 *     batch_init() provides default values for the messages.
 *     'title': title for the progress page.
 *       Defaults to t('Processing').
 *     'init_message': message displayed while the processing is initialized.
 *       Defaults to t('Initializing.').
 *     'progress_message': message displayed while processing the batch.
 *       Available placeholders are @current, @remaining, @total and @percent.
 *       Defaults to t('Remaining @remaining of @total.').
 *     'error_message': message displayed if an error occurred while processing
 *       the batch.
 *       Defaults to t('An error has occurred.').
 *     'finished': the name of a function to be executed after the batch has
 *       completed. This should be used to perform any result massaging that
 *       may be needed, and possibly save data in $_SESSION for display after
 *       final page redirection.
 *     'file': the path to the file containing the definitions of the
 *       'operations' and 'finished' functions, for instance if they don't
 *       reside in the original '.module' file. The path should be relative to
 *       the base_path(), and thus should be built using drupal_get_path().
 *
 * Operations are added as new batch sets. Batch sets are used to ensure
 * clean code independence, ensuring that several batches submitted by
 * different parts of the code (core / contrib modules) can be processed
 * correctly while not interfering or having to cope with each other. Each
 * batch set gets to specify his own UI messages, operates on its own set
 * of operations and results, and triggers its own 'finished' callback.
 * Batch sets are processed sequentially, with the progress bar starting
 * fresh for every new set.
 */
function batch_set($batch_definition) {
jhodgdon’s picture

Version: 6.x-dev » 7.x-dev

It's poorly formatted on api.drupal.org (the components should have - in front of each one, to format as a bullet list), but it looks like the API documentation for http://api.drupal.org/api/function/batch_set/6 does say that one component is:

'file': the path to the file containing the definitions of the
'operations' and 'finished' functions, for instance if they don't
reside in the original '.module' file. The path should be relative to
the base_path(), and thus should be built using drupal_get_path().

It looks like you are asking for the documentation on this page http://api.drupal.org/api/group/batch/6 to be updated with the optional 'file' parameter in its example?

I wonder how common it is that the functions in the batch_set() call would not be in the main module file (the example doesn't do anything with many of the optional parameters), and (assuming the formatting was fixed) whether the above documentation in batch_set() is enough?

Anyway, if this is to be patched, I think the formatting issue in batch_set() should also be fixed, and it should also be patched in Drupal 7 first and then back ported to Drupal 6.

markDrupal’s picture

yeah the example (http://api.drupal.org/api/group/batch/6) is what I had problems with, after walking through the example, I got no feedback in the form of error messages from the website that my batch was not run, and given that it is a batch job it was difficult to debug and pin point the error back to the missing 'file' declaration

BTW, I thought Drupal 7 has some sort of auto loading of files feature so this may not be required any more after 6.

jhodgdon’s picture

Status: Needs work » Needs review
StatusFileSize
new4.68 KB

Drupal 7's function registry was removed -- they found it didn't help with performance.

Anyway, here's a patch for the doc in Drupal 7. Should fix the formatting issues on batch_set() and also adds a file component to the example in the overall batch group doc.

If accepted, should be ported to D6 as well.

Status: Needs review » Needs work

The last submitted patch failed testing.

jhodgdon’s picture

Status: Needs work » Needs review
StatusFileSize
new5.12 KB

Here's a patch reroll. Also needs port to Drupal 6 if accepted.

yched’s picture

Status: Needs review » Needs work

Patch looks good except for the 3rd person in the one-line descriptions in PHPdocs.

jhodgdon’s picture

Status: Needs work » Needs review

They are supposed to be 3rd person. See http://drupal.org/node/1354

yched’s picture

Status: Needs review » Reviewed & tested by the community

I stand corrected: http://drupal.org/node/487802#comment-1740560.
Patch is ready, then.

Side note: http://drupal.org/node/1354 also says Implements hook_help(). while everything in core D7 still uses Implement hook_help()., so it kind of questions the validity of the doc. Pointing to webchick's decision linked above could be clearer in-between ;-)

webchick’s picture

Version: 7.x-dev » 6.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)

Yes, I've been desperately wanting a patch to bulk-change those all to "Implements" since the documentation was updated. Sigh.

Anyway, committed to HEAD. :) Moving down to 6.x.

jhodgdon’s picture

I hear you webchick. Will consider doing such a patch. Do we have an issue already?

jhodgdon’s picture

The D7 "fix all the Implement hook_foo()" issue:
#502190: Hook implementation headers out of compliance with standards
if anyone is interested.

jhodgdon’s picture

Status: Patch (to be ported) » Needs review
StatusFileSize
new4.66 KB

Here's a patch for Drupal 6. It appears that the 'css' and 'url_options' components are new to Drupal 7; otherwise, the resulting doc is the same as the committed D7 patch, I think.

markDrupal’s picture

Awesome! Thanks for getting this committed.

jhodgdon’s picture

The Drupal 7 patch has been committed. The Drupal 6 patch still needs someone other than me to mark it "Reviewed and Tested by the Community" before it can be committed.

yched’s picture

Patch is correct, except *D6* does not use 3rd person for function descriptors ;-).

jhodgdon’s picture

D6 is inconsistent in this regard. There was no standard for this when D6 was released, and if you look at function headers for D6, you'll find a mix. So, when updating function headers, I tend to update them to our current coding standards, which are not marked anywhere as being version-dependent by the way! :)

yched’s picture

Status: Needs review » Reviewed & tested by the community

Makes sense. You win again ;-)

gábor hojtsy’s picture

Status: Reviewed & tested by the community » Fixed

Committed to Drupal 6, thanks.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.