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,
':never' => AGGREGATOR_CLEAR_NEVER,
));
$queue = DrupalQueue::get('aggregator_feeds');
foreach ($result as $feed) {
if ($queue->createItem($feed)) {
// Add timestamp to avoid queueing item more than once.
db_update('aggregator_feed')
->fields(array('queued' => REQUEST_TIME))
->condition('fid', $feed->fid)
->execute();
}
}
// Remove queued timestamp after 6 hours assuming the update has failed.
db_update('aggregator_feed')
->fields(array('queued' => 0))
->condition('queued', REQUEST_TIME - (3600 * 6), '<')
->execute();
}
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())) {
$function($item->data);
$queue->deleteItem($item);
}
}
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.