I'm using batch API in a custom module to clone millions of nodes programmatically but I am facing an error:
An error occurred. /batch?id=7&op=do
Fatal error: Out of memory (allocated -1179648000) (tried to allocate 40961 bytes) in
I try to optimize my code using the varible $limit for processing by lot but it seem to be not work
For example I have 10 data in my database and I put $ limit = 5; and it recovers only 5 data
But according the document http://envisioninteractive.com/drupal/drupal-batch-api-in-a-nutshell/ the limit Set the number of nodes you want to create within a single iteration of the batch. This number should be pretty low as it is the reason why we're creating the batch process in the first place.
here is my code :
function mymodule_menu() {
$items = array();
$items['mymodule'] = array(
'title' => t('Cloner une liste'),
'page callback' => 'drupal_get_form',
'page arguments' => array('mymodule_form'),
'access arguments' => array('access content'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function mymodule_form() {
global $base_url;
$return_url = $base_url .'/gestion_creche_liste/'.arg(1);
$node_tmp = node_load(arg(1));
$default = 'Clone de ' . $node_tmp->title;
$form['title_liste'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => $default,
'#required' => TRUE,
);
$form['description_liste'] = array(
'#type' => 'textarea',
'#title' => t('Description'),
'#required' => false,
);
$form['retour'] = array(
'#type' => 'button',
'#value' => t('Retour'),
'#prefix' => '',
'#attributes' => array('onClick' => "window.location.href='".$return_url."'; return true;"),
'#post_render' => array('change_button_type'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save')
);
return $form;
}
function theme_questionnaire_etape_trois_formulaire($form){
$output = '';
$output .= '<p><label for="edit-title_liste_value"><span> Titre liste * : </span>';
$output .= str_replace('div','t',drupal_render($form['title_liste']));
$output .= '</label></p>';
$output .= '<p><label for="edit-field_description_liste_value"><span>Description : </span>';
$output .= str_replace('div','t',drupal_render($form['description_liste']));
$output .= '</label></p>';
$output .= '<div id="btn">';
$output .= drupal_render($form['submit']);
$output .= '</div>';
$output .= drupal_render($form);
return $output;
}
function mymodule_form_submit($form, &$form_state) {
$batch = array(
'operations' => array(
array('batch_clonerliste_op', array($form_state['values']['title_liste'],$form_state['values']['description_liste'])),
array('batch_mymodule_op', array(arg(1))),
),
'finished' => 'batch_mymodule_finished',
'title' => t('Processing Example Batch'),
'init_message' => t('Clone is starting'),
'progress_message' => t('Processed @current out of @total.'),
'error_message' => t('Example Batch has encountered an error.'),
);
batch_set($batch);
}
function batch_clonerliste_op($options1,$options2,&$context) {
if(!isset($context['sandbox']['progress'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['max'] = 1;
}
$node_liste = new stdClass();
$node_liste->type = 'liste';
$node_liste->language = 'fr';
$node_liste->title = $options1;
$node_liste->field_description_liste[0]['value'] = $options2;
node_save($node_liste);
$context['results']['nid'] = $node_liste->nid;
$context['sandbox']['progress']++;
$context['message'] = t('Now processing %node', array('%node' => $node_liste->title));
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
function batch_mymodule_op($options3,&$context) {
$nid_liste = $context['results']['nid'];
$tmp = get_curent_creche_liste($options3);
$total = $num_rows = db_result(
db_query("SELECT COUNT(DISTINCT nid) FROM {content_field_liste_creche} WHERE field_liste_creche_nid = '%s'",$options3));
if (!isset($context['sandbox']['progress'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['current_node'] = 0;
$context['results'][] = 0;
$context['sandbox']['max'] = $total;
}
//in total i have 10 date inside my database for exemple and i set limit = 5 $limit = 5;
$result = db_query_range("SELECT DISTINCT nid FROM {content_field_liste_creche} where field_liste_creche_nid = %s and nid != %d", array($options3,$context['sandbox']['current_node']), 0, $limit);
while ($row = db_fetch_array($result)) {
$node = node_load($row['nid'],NULL,TRUE);
$node->field_liste_creche[]['nid'] = $nid_liste;
$node = node_submit($node);
node_save($node);
$context['sandbox']['progress']++;
$context['results'][]++;
$context['sandbox']['current_node'] = $node->nid;
$context['message'] = t('Now processing %node', array('%node' => $node->title));
}
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
function batch_mymodule_finished($success, $results, $operations) {
if ($success) {
$message = count($results)-2 .' processed.';
}
else {
$error_operation = reset($operations);
$message = 'An error occurred while processing ' . $error_operation[0] . ' with arguments :' . print_r($error_operation[0], TRUE);
}
drupal_set_message($message);
drupal_set_message('Clone réussie');
drupal_goto('gestion_liste');
}
function get_curent_creche_liste($nid_list){
$nid_creche_list = array();
$query = "SELECT DISTINCT nid FROM content_field_liste_creche WHERE field_liste_creche_nid ='".$nid_list."'";
$result = db_query($query);
while ($row =db_fetch_object($result)) {
$nid_creche_list[] = $row->nid;
}
return $nid_creche_list;
}
thank you very much in advance for your help