I've written a custom module that adds many users from a database to drupal database. So, it has many database queries to take care of the drupal tables: users, user_roles, url_alias, profile and field_data_field_$fieldname and field_revision_field_$fieldname where $fieldname is the profile2 field and has many such fields.

The problem is when I execute this module (the trigger is user selects an option in the form which is specific for this module), it executed for only 30 seconds and inserted some 20+ users where I have to insert 500+ users. After 30 seconds, it didn't display any error. It stayed on the same form.

How can I clear this?

3 Answers 3


You need write batch operation:

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.


  • another solution is keep migrated row's ID in separated table or flag theme and continue migrate on remained rows Jun 30, 2012 at 20:19

You can implement hook_cron() in your module. As example, you can look at aggregator_cron(), which imports new feed articles from a list of feeds.

function aggregator_cron() {
  $result = db_query('SELECT * FROM {aggregator_feed} WHERE queued = 0 AND checked + refresh < :time AND refresh <> :never', array(
    ':time' => REQUEST_TIME, 
  $queue = DrupalQueue::get('aggregator_feeds');
  foreach ($result as $feed) {
    if ($queue->createItem($feed)) {
      // Add timestamp to avoid queueing item more than once.
        ->fields(array('queued' => REQUEST_TIME))
        ->condition('fid', $feed->fid)

  // Remove queued timestamp after 6 hours assuming the update has failed.
    ->fields(array('queued' => 0))
    ->condition('queued', REQUEST_TIME - (3600 * 6), '<')

I took this implementation of hook_cron() because it has a similar task, although the data is not imported from another database, and because it shows how to use Drupal 7 queues.

The other function you should look is aggregator_cron_queue_info(), which is an implementation of hook_cron_queue_info(), which defines the queue cron task would automatically consume. To understand how this work, see drupal_cron_run(), which contains the following code.

  // Grab the defined cron queues.
  $queues = module_invoke_all('cron_queue_info');
  drupal_alter('cron_queue_info', $queues);

  // …

  foreach ($queues as $queue_name => $info) {
    $function = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get($queue_name);
    while (time() < $end && ($item = $queue->claimItem())) {

To notice that the queue doesn't need to be populated from hook_cron(), but it can get populated from any hook.

The reason for using a queue is explained in the documentation for hook_cron_queue_info().

While there can be only one hook_cron() process running at the same time, there can be any number of processes defined here running. Because of this, long running tasks are much better suited for this API. Items queued in hook_cron() might be processed in the same cron run if there are not many items in the queue, otherwise it might take several requests, which can be run in parallel.


This is most likely a restriction set in your php.ini . Just search for 30 in the php.ini and set the value to something more usefull for you.

As an alternative you can trigger your code using drush eval or even code your own drush command. Drush is executed as PHP command line (CLI) and does not have any execution time restriction. The drush module itself has nice example code to learn from.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.