You are here

background_process.module in Background Process 7.2

File

background_process.module
View source
<?php

/**
 * @file
 * This module implements a framework for calling funtions in the background.
 *
 * @code
 * $handle = background_process_start('mymodule_dosomething', $myvar1, $myvar2);
 * $handle = background_process_start(array('myclass', 'mystaticfunction'), $myvar1, $myvar2);
 * $handle = background_process_start(array($myobject, 'mymethod'), $myvar1, $myvar2);
 * $handle = background_process_start_locked('dontrunconcurrently', 'mymodule_dosomething', $myvar1, $myvar2);
 * @endcode
 *
 * For implementation of load balancing functionality:
 * @see hook_service_group()
 *
 * @todo Administration interface for settings and viewing running processes
 * @todo Clean up orphan handles whos request did not make it through to the service (add expiration?)
 * @todo Add SSL support for service calls?
 * @todo Add functionality for killing keep alive requests?
 */
include 'background_process.inc';
include 'background_process.http.inc';
define('BACKGROUND_PROCESS_SERVICE_TIMEOUT', 0);
define('BACKGROUND_PROCESS_CONNECTION_TIMEOUT', 2);
define('BACKGROUND_PROCESS_STREAM_TIMEOUT', 2);
define('BACKGROUND_PROCESS_CLEANUP_AGE', 120);
define('BACKGROUND_PROCESS_RUNNING_CLEANUP_AGE', 8 * 3600);
define('BACKGROUND_PROCESS_QUEUE_CLEANUP_AGE', 86400);
define('BACKGROUND_PROCESS_RESULT_CLEANUP_AGE', 3600);
define('BACKGROUND_PROCESS_DRUSH_CMD', '/usr/local/bin/drush');
define('BACKGROUND_PROCESS_QUEUE_NAME', 'background_process');
define('BACKGROUND_PROCESS_STATUS_NONE', 0);
define('BACKGROUND_PROCESS_STATUS_LOCKED', 1);
define('BACKGROUND_PROCESS_STATUS_RUNNING', 2);
define('BACKGROUND_PROCESS_STATUS_QUEUED', 3);
define('BACKGROUND_PROCESS_STATUS_DISPATCHED', 4);

// ---------- HOOKS ----------

/**
 * Implements hook_menu().
 */
function background_process_menu() {
  $items = array();
  $items['bgp-start/%'] = array(
    'type' => MENU_CALLBACK,
    'title' => 'Run background process',
    'description' => 'Run background process',
    'page callback' => 'background_process_service_start',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'background_process_service_access',
    'access arguments' => array(
      1,
    ),
  );
  $items['background-process/unlock/%background_process'] = array(
    'type' => MENU_CALLBACK,
    'title' => 'Unlock background process',
    'description' => 'Unlock background process',
    'page callback' => 'background_process_service_unlock',
    'page arguments' => array(
      2,
    ),
    'access arguments' => array(
      'administer background process',
    ),
  );
  $items['background-process/check-token'] = array(
    'type' => MENU_CALLBACK,
    'title' => 'Check background process token',
    'description' => 'Check background process token',
    'page callback' => 'background_process_check_token',
    'page arguments' => array(
      2,
    ),
    'access callback' => TRUE,
    'file' => 'background_process.pages.inc',
  );
  $items['admin/config/system/background-process/settings'] = array(
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'title' => 'Settings',
    'weight' => 1,
  );
  $items['admin/config/system/background-process'] = array(
    'title' => 'Background process',
    'description' => 'Administer background processes',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'background_process_settings_form',
    ),
    'access arguments' => array(
      'administer background process',
    ),
    'file' => 'background_process.admin.inc',
  );
  $items['admin/config/system/background-process/overview'] = array(
    'type' => MENU_LOCAL_TASK,
    'title' => 'Overview',
    'description' => 'Administer background processes',
    'page callback' => 'background_process_overview_page',
    'access arguments' => array(
      'administer background process',
    ),
    'file' => 'background_process.admin.inc',
    'weight' => 3,
  );
  $items['admin/config/system/background-process/dispatchers/settings'] = array(
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'title' => 'Settings',
    'weight' => 1,
  );
  $items['admin/config/system/background-process/dispatchers'] = array(
    'type' => MENU_LOCAL_TASK,
    'title' => 'Dispatchers',
    'description' => 'Administer dispatchers',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'background_process_dispatchers_form',
    ),
    'access arguments' => array(
      'administer background process',
    ),
    'file' => 'background_process.admin.inc',
    'weight' => 3,
  );
  $items['admin/config/system/background-process/dispatchers/http'] = array(
    'type' => MENU_LOCAL_TASK,
    'title' => 'HTTP',
    'description' => 'Administer HTTP dispatcher',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'background_process_http_dispatcher_form',
    ),
    'access arguments' => array(
      'administer background process',
    ),
    'file' => 'background_process.admin.inc',
    'weight' => 3,
  );
  $items['admin/config/system/background-process/dispatchers/drush'] = array(
    'type' => MENU_LOCAL_TASK,
    'title' => 'Drush',
    'description' => 'Administer Drush dispatcher',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'background_process_drush_dispatcher_form',
    ),
    'access arguments' => array(
      'administer background process',
    ),
    'file' => 'background_process.admin.inc',
    'weight' => 3,
  );
  $items['admin/config/system/background-process/dispatchers/queue'] = array(
    'type' => MENU_LOCAL_TASK,
    'title' => 'Queue',
    'description' => 'Administer queue dispatcher',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'background_process_queue_dispatcher_form',
    ),
    'access arguments' => array(
      'administer background process',
    ),
    'file' => 'background_process.admin.inc',
    'weight' => 3,
  );
  return $items;
}

/**
 * Implements background_process_dispatcher_info().
 */
function background_process_background_process_dispatcher_info() {
  $common = array(
    'file' => drupal_get_path('module', 'background_process') . '/background_process.dispatchers.inc',
  );
  $items = array(
    'http' => array(
      'callback' => 'background_process_dispatcher_http',
      'title callback' => 'background_process_dispatcher_http_title',
      'options callback' => 'background_process_dispatcher_http_options',
    ) + $common,
    'drush' => array(
      'callback' => 'background_process_dispatcher_drush',
      'title callback' => 'background_process_dispatcher_drush_title',
      'options callback' => 'background_process_dispatcher_drush_options',
    ) + $common,
    'queue' => array(
      'callback' => 'background_process_dispatcher_queue',
      'title callback' => 'background_process_dispatcher_queue_title',
      'options callback' => 'background_process_dispatcher_queue_options',
    ) + $common,
    'foreground' => array(
      'callback' => 'background_process_dispatcher_foreground',
      'title callback' => 'background_process_dispatcher_foreground_title',
    ) + $common,
  );
  return $items;
}
function background_process_get_dispatchers() {
  $dispatchers =& drupal_static(__FUNCTION__);
  if (!isset($dispatchers)) {
    $cache = cache_get('background_process_dispatcher_info');
    if ($cache) {
      $dispatchers = $cache->data;
    }
    else {
      $dispatchers = module_invoke_all('background_process_dispatcher_info');
      drupal_alter('background_process_dispatcher_info', $dispatchers);
      cache_set('background_process_dispatcher_info', $dispatchers, 'cache');
    }
  }
  return $dispatchers;
}
function background_process_prepare_dispatcher_callback($dispatcher, $type = NULL) {
  $dispatchers = background_process_get_dispatchers();
  if (empty($dispatchers[$dispatcher])) {
    throw new Exception(t('Dispatcher: %dispatcher not found', array(
      '%dispatcher' => $dispatcher,
    )));
  }
  if (isset($dispatchers[$dispatcher])) {
    include_once $dispatchers[$dispatcher]['file'];
  }
  $key = ($type ? $type . ' ' : '') . 'callback';
  return isset($dispatchers[$dispatcher][$key]) ? $dispatchers[$dispatcher][$key] : NULL;
}
function background_process_invoke_dispatcher($dispatcher, $process) {
  $callback = background_process_prepare_dispatcher_callback($dispatcher);
  return call_user_func($callback, $process);
}
function background_process_get_service_host_title($service_host) {
  if ($callback = background_process_prepare_dispatcher_callback($service_host['dispatcher'], 'title')) {
    return call_user_func($callback, $service_host);
  }
  return '';
}
function background_process_get_service_host_options($service_host) {
  if ($callback = background_process_prepare_dispatcher_callback($service_host['dispatcher'], 'options')) {
    return call_user_func($callback, $service_host);
  }
  return array();
}

/**
 * Implements hook_permission().
 */
function background_process_permission() {
  return array(
    'administer background process' => array(
      'title' => t('Administer background processes'),
      'description' => t('Perform administration tasks for background processes.'),
    ),
  );
}

/**
 * Implements hook_cron_queue_info().
 */
function background_process_cron_queue_info() {
  $default = variable_get('background_process_queue_name', BACKGROUND_PROCESS_QUEUE_NAME);
  $queues = array();
  $queues[$default] = array(
    'worker callback' => 'background_process_cron_queue_worker',
  );
  $service_hosts = background_process_get_service_hosts();
  foreach ($service_hosts as $service_host) {
    if ($service_host['dispatcher'] == 'queue' && isset($service_host['queue']) && !isset($queues[$service_host['queue']])) {
      $queues[$service_host['queue']] = $queues[$default];
    }
  }
  return $queues;
}
function background_process_cron_queue_worker($pid) {
  if ($process = BackgroundProcess::load($pid)) {
    $process
      ->execute();
  }
  else {
    watchdog('bgprocess', 'Process: @pid not found', array(
      '@pid' => $pid,
    ), WATCHDOG_ERROR);
  }
}

/**
 * Implements hook_cron().
 */
function background_process_cron() {

  // Don't run for more than 2 minutes. If timeout exceeds, the rest will be handled during the next run.
  $expire = 120;
  set_time_limit($expire);

  // Redispatch requests that didn't make it through
  $time = time();
  $pids = array(
    0,
  );

  // Easier to just do a NOT IN (0), than make a conditional query build below :-)
  do {
    if (time() >= $_SERVER['REQUEST_TIME'] + $expire) {
      break;
    }
    $results = db_select('background_process', 'bp', array(
      'target' => 'background_process',
    ))
      ->fields('bp')
      ->condition('bp.created', time() - 10, '<')
      ->condition('bp.created', time() - variable_get('background_process_cleanup_age', BACKGROUND_PROCESS_CLEANUP_AGE), '>')
      ->condition('bp.exec_status', BACKGROUND_PROCESS_STATUS_LOCKED)
      ->condition('bp.pid', $pids, 'NOT IN')
      ->range(0, 10)
      ->orderBy('bp.pid')
      ->execute()
      ->fetchAll(PDO::FETCH_OBJ);
    foreach ($results as $result) {
      $pids[] = $result->pid;
      $process = BackgroundProcess::create($result);
      $process
        ->reDispatch();
      watchdog('bg_process', 'Redispatched process %handle (%pid)', array(
        '%handle' => $process->handle,
        '%pid' => $process->pid,
      ), WATCHDOG_INFO);
    }
  } while (!empty($results));

  // Cleanup old requests that never started
  $time = time();
  $msg = t('Never started (auto unlock due to timeout)');
  do {
    if (time() >= $_SERVER['REQUEST_TIME'] + $expire) {
      break;
    }
    $results = db_select('background_process', 'bp', array(
      'target' => 'background_process',
    ))
      ->fields('bp')
      ->condition('bp.created', time() - variable_get('background_process_cleanup_age', BACKGROUND_PROCESS_CLEANUP_AGE), '<')
      ->condition('bp.exec_status', BACKGROUND_PROCESS_STATUS_LOCKED)
      ->range(0, 10)
      ->orderBy('bp.pid')
      ->execute()
      ->fetchAll(PDO::FETCH_OBJ);
    foreach ($results as $result) {
      $process = BackgroundProcess::create($result);
      $process
        ->log($msg)
        ->unlock();
      watchdog('bg_process', 'Background process %handle (%pid) unlocked: !msg', array(
        '%handle' => $process->handle,
        '%pid' => $process->pid,
        '!msg' => $msg,
      ), WATCHDOG_INFO);
    }
  } while (!empty($results));

  // Cleanup stale requests
  $time = time();
  $msg = t('Never finished (auto unlock due to long run)');
  do {
    if (time() >= $_SERVER['REQUEST_TIME'] + $expire) {
      break;
    }
    $results = db_select('background_process', 'bp', array(
      'target' => 'background_process',
    ))
      ->fields('bp')
      ->condition('bp.start_stamp', $time - variable_get('background_process_running_cleanup_age', BACKGROUND_PROCESS_RUNNING_CLEANUP_AGE), '<')
      ->condition('bp.exec_status', BACKGROUND_PROCESS_STATUS_RUNNING)
      ->range(0, 10)
      ->execute()
      ->fetchAll(PDO::FETCH_OBJ);
    foreach ($results as $result) {
      $process = BackgroundProcess::create($result);
      $process
        ->log($msg)
        ->unlock();
      watchdog('bg_process', 'Background process %handle (%pid) unlocked: !msg', array(
        '%handle' => $process->handle,
        '%pid' => $process->pid,
        '!msg' => $msg,
      ), WATCHDOG_INFO);
    }
  } while (!empty($results));

  // Cleanup queued requests that were never processed
  $time = time();
  $msg = t('Never started (auto unlock due to timeout)');
  do {
    if (time() >= $_SERVER['REQUEST_TIME'] + $expire) {
      break;
    }
    $results = db_select('background_process', 'bp', array(
      'target' => 'background_process',
    ))
      ->fields('bp')
      ->condition('bp.created', $time - variable_get('background_process_queue_cleanup_age', BACKGROUND_PROCESS_QUEUE_CLEANUP_AGE), '<')
      ->condition('bp.exec_status', BACKGROUND_PROCESS_STATUS_QUEUED)
      ->range(0, 10)
      ->execute()
      ->fetchAll(PDO::FETCH_OBJ);
    foreach ($results as $result) {
      $process = BackgroundProcess::create($result);
      $process
        ->log($msg)
        ->unlock();
      watchdog('bg_process', 'Background process %handle (%pid) unlocked: !msg', array(
        '%handle' => $process->handle,
        '%pid' => $process->pid,
        '!msg' => $msg,
      ), WATCHDOG_INFO);
    }
  } while (!empty($results));

  // Cleanup result log
  $time = time();
  do {
    if (time() >= $_SERVER['REQUEST_TIME'] + $expire) {
      break;
    }
    $pids = db_select('background_process_result', 'r', array(
      'target' => 'background_process',
    ))
      ->fields('r', array(
      'pid',
    ))
      ->condition('r.created', $time - variable_get('background_process_result_cleanup_age', BACKGROUND_PROCESS_RESULT_CLEANUP_AGE), '<')
      ->range(0, 100)
      ->execute()
      ->fetchAllKeyed(0, 0);
    if ($pids) {
      db_delete('background_process_result', array(
        'target' => 'background_process',
      ))
        ->condition('pid', $pids, 'IN')
        ->execute();
    }
  } while (!empty($pids));
}

/**
 * Implements hook_schedule_alter().
 *
 * Cleaning up is important. If our cron job is scheduled,
 * make sure it's run first.
 */
function background_process_cron_schedule_alter(&$items) {

  // We need to unlock ourselves if we're stale (chicken and the egg...)
  if (!isset($items['background_process_cron'])) {
    $hooks = ultimate_cron_get_hooks();
    if (isset($hooks['background_process_cron']['background_process'])) {
      $process =& $hooks['background_process_cron']['background_process'];

      // Self unlock if too old ...
      if ($process && $process
        ->getStartTime() + 120 < time()) {
        $process
          ->log(t('Self unlocking stale cleanup job'))
          ->unlock();
        $process = NULL;
      }
    }
  }

  // Put our cron job first in the list.
  if (isset($items['background_process_cron'])) {
    $org_items = $items;
    $items = array();
    $items['background_process_cron'] = $org_items['background_process_cron'];
    $items += $org_items;
  }
}

/**
 * Implements hook_watchdog().
 */
function background_process_watchdog($log = array()) {
  if ($process = BackgroundProcess::currentProcess()) {
    $log['variables'] = is_array($log['variables']) ? $log['variables'] : array();
    $process
      ->log(t($log['message'], $log['variables']), $log['severity']);
  }
}

/**
 * Implements hook_service_group().
 *
 * Default load balancing using pseudo round-robin.
 */
function background_process_service_group() {
  $info = array();
  $info['methods']['background_process_service_group_round_robin'] = t('Pseudo round-robin');
  $info['methods']['background_process_service_group_random'] = t('Random');
  $info['methods']['background_process_service_group_idle'] = t('Idle');
  return $info;
}

/**
 * Load balancing based on random pick.
 */
function background_process_service_group_random($service_group) {
  return $service_group['hosts'][rand(0, count($service_group['hosts']) - 1)];
}

/**
 * Round-robin load balancing based on random pick.
 */
function background_process_service_group_round_robin($service_group) {
  static $idx = NULL;
  if (isset($idx)) {
    $idx = ($idx + 1) % count($service_group['hosts']);
  }
  else {
    $idx = rand(0, count($service_group['hosts']) - 1);
  }
  return $service_group['hosts'][$idx];
}

/**
 * Load balancing based on most idle clients.
 */
function background_process_service_group_idle($service_group) {
  $current = array(
    'host' => reset($service_group['hosts']),
    'clients' => -1,
  );
  $service_hosts = background_process_get_service_hosts();
  foreach ($service_group['hosts'] as $host) {
    $clients = background_process_current_clients($host);
    $max_clients = $service_hosts[$host]['max_clients'];
    $available = $max_clients - $clients;
    if ($available && $current['clients'] < $available) {
      $current = array(
        'host' => $host,
        'clients' => $available,
      );
    }
  }
  if ($current['clients'] == -1) {

    // No candidate found, use pseudo round-robin
    $current['host'] = background_process_service_group_round_robin($service_group);
  }
  return $current['host'];
}

/**
 * Access handler for service call
 */
function background_process_service_access($pid) {

  // Ensure no session!
  drupal_save_session(FALSE);
  unset($_SESSION);
  $process = BackgroundProcess::load($pid);
  if (!$process) {
    watchdog('bg_process', 'Unknown process: %pid', array(
      '%pid' => $pid,
    ));
    return FALSE;
  }
  $token = $_POST['token'];
  if ($token !== $process
    ->getToken()) {
    watchdog('bg_process', 'Invalid token: %token for handle: %handle', array(
      '%token' => $token,
      '%handle' => $process
        ->getHandle(),
    ));
    return FALSE;
  }
  return TRUE;
}

// ---------- HELPER FUNCTIONS ----------
function background_process_current_clients($service_host) {
  $clients = db_query("SELECT COUNT(1) FROM {background_process} WHERE service_host = :service_host", array(
    ':service_host' => $service_host,
  ), array(
    'target' => 'background_process',
  ))
    ->fetchField();
  return $clients;
}

/**
 * Load a background process
 *
 * @param $pid
 *   Process ID to load
 */
function background_process_load($pid) {
  if (is_numeric($pid)) {
    return BackgroundProcess::load($pid);
  }
  else {
    return BackgroundProcess::loadByHandle($pid);
  }
}

/**
 * Unlock background process.
 *
 * @param $handle
 *   Handle of process to unlock
 */
function background_process_service_unlock($process) {
  global $user;
  if ($process
    ->log(t('Manually unlocked by @user', array(
    '@user' => $user->name,
  )))
    ->unlock()) {
    drupal_set_message(t('Process %handle unlocked', array(
      '%handle' => $process->handle,
    )));
  }
  else {
    drupal_set_message(t('Process %handle could not be unlocked', array(
      '%handle' => $process->handle,
    )), 'error');
  }
  drupal_goto();
}

/**
 * Call the function requested by the service call
 *
 * @param $callback
 *   Function to call
 *
 */
function background_process_service_start($pid) {

  // Let's clean up the mess the menu-router system leaves behind.
  $cid = 'menu_item:' . hash('sha256', $_GET['q']);
  drupal_register_shutdown_function('cache_clear_all', $cid, 'cache_menu');
  $process = BackgroundProcess::load($pid);
  if (!$process) {
    watchdog('bg_process', 'Unknown process: %pid', array(
      '%pid' => $pid,
    ), WATCHDOG_ERROR);
  }
  $process
    ->execute();
  exit;
}

/**
 * Get service hosts defined in the system.
 */
function background_process_get_service_hosts() {
  global $base_url;
  $default_options = array(
    'max_clients' => -1,
  );

  // Get defined service groups
  $service_hosts = variable_get('background_process_service_hosts', array());
  $service_hosts += array(
    'default' => array(
      'dispatcher' => 'http',
      'base_url' => $base_url,
    ),
  );

  // Populate service hosts with default options
  foreach ($service_hosts as &$service_host) {
    $service_host += background_process_get_service_host_options($service_host) + $default_options;
  }
  return $service_hosts;
}

/**
 * Get service hosts defined in the system.
 */
function background_process_get_service_groups() {
  $default_options = array(
    'method' => 'background_process_service_group_round_robin',
  );

  // Get defined service groups
  $service_groups = variable_get('background_process_service_groups', array());
  $service_groups += array(
    'default' => array(
      'hosts' => array(
        variable_get('background_process_default_service_host', 'default'),
      ),
    ),
  );

  // Populate service groups with default options
  foreach ($service_groups as &$service_group) {
    $service_group += $default_options;
  }
  return $service_groups;
}

// ---------- INTERNAL FUNCTIONS ----------

/**
 * Get string name of callback.
 *
 * @param $callback
 *   Callback can be either a string or an array.
 * @return string
 *   The name of the callback, e.g. 'myfunction', 'myclass::mystaticmethod' or 'myclass->mymethod'.
 */
function _background_process_callback_name($callback) {
  if (is_array($callback)) {
    if (is_object($callback[0])) {
      $callback = get_class($callback[0]) . '->' . $callback[1];
    }
    else {
      $callback = $callback[0] . '::' . $callback[1];
    }
  }
  return $callback;
}

// ---------- EXTERNAL API (legacy 1.x) ----------

/**
 * Get/set current handle.
 *
 * @staticvar $current_handle
 * @param $handle
 * @return string
 *   Current handle.
 */
function background_process_current_handle($handle = NULL) {
  $process = BackgroundProcess::currentProcess();
  return $process
    ->getHandle();
}

/**
 * Restart the current background process
 *
 * @return
 *   Exception on fail, otherwise exit
 */
function background_process_restart() {
  $process = BackgroundProcess::currentProcess();
  $process
    ->restart();
  exit;
}

/**
 * Keep the current background process alive
 * (meaning restart it when it exits)
 */
function background_process_keepalive() {
  $process = BackgroundProcess::currentProcess();
  $process
    ->keepAlive();
}

/**
 * Start background process
 *
 * Calls the service handler through http passing function arguments as serialized data
 * Be aware that the callback will run in a new request
 *
 * @global string $base_url
 *   Base URL for this Drupal request
 *
 * @param $callback
 *   Function to call
 * @param $var [, $... ]]
 *   Arbitrary number of variables to pass on to the callback
 * @return mixed
 *   Handle on success, FALSE on failure
 */
function background_process_start($callback) {
  $args = func_get_args();
  $callback = array_shift($args);
  return BackgroundProcess::lock()
    ->setCallback($callback, $args)
    ->dispatch()
    ->getHandle();
}

/**
 * Start locked background process
 *
 * Calls the service handler through http passing function arguments as serialized data
 * Be aware that the callback will run in a new request
 *
 * @global string $base_url
 *   Base URL for this Drupal request
 *
 * @param $handle
 *   Handle to give background process
 * @param $callback
 *   Function to call
 * @param $var [, $... ]]
 *   Arbitrary number of variables to pass on to the callback
 * @return mixed
 *   Handle on success, FALSE on failure
 */
function background_process_start_locked($handle, $callback) {
  $args = func_get_args();
  $handle = array_shift($args);
  $callback = array_shift($args);
  return BackgroundProcess::lock($handle)
    ->setCallback($callback, $args)
    ->dispatch()
    ->getHandle();
}

/**
 * Start background process
 *
 * Queue the function call passing function arguments as serialized data
 * Be aware that the callback will run in a new request
 *
 * @global string $base_url
 *   Base URL for this Drupal request
 *
 * @param $callback
 *   Function to call
 * @param $var [, $... ]]
 *   Arbitrary number of variables to pass on to the callback
 * @return mixed
 *   Handle on success, FALSE on failure
 */
function background_process_queue($callback) {
  $args = func_get_args();
  $callback = array_shift($args);
  return BackgroundProcess::lock()
    ->setCallback($callback, $args)
    ->queue()
    ->getHandle();
}

/**
 * Queue locked background process
 *
 * Queue the function call passing function arguments as serialized data
 * Be aware that the callback will run in a new request
 *
 * @global string $base_url
 *   Base URL for this Drupal request
 *
 * @param $handle
 *   Handle to give background process
 * @param $callback
 *   Function to call
 * @param $var [, $... ]]
 *   Arbitrary number of variables to pass on to the callback
 * @return mixed
 *   Handle on success, FALSE on failure
 */
function background_process_queue_locked($handle, $callback) {
  $args = func_get_args();
  $handle = array_shift($args);
  $callback = array_shift($args);
  return BackgroundProcess::lock($handle)
    ->setCallback($callback, $args)
    ->queue()
    ->getHandle();
}

/**
 * Get background process
 *
 * @param $handle
 *   Handle of background process
 * @return object
 *   Background process
 */
function background_process_get_process($handle) {
  return BackgroundProcess::loadByHandle($handle);
}

/**
 * Update background process status
 *
 * @param $handle
 *   Handle of background process
 * @param $status
 *   Status to set for the background process
 * @return object
 *   Background process
 */
function background_process_update_status($handle, $status) {
  $process = BackgroundProcess::loadByHandle($handle);
  $process
    ->setStatus($status)
    ->writeData();
  return $process;
}

Functions

Namesort descending Description
background_process_background_process_dispatcher_info Implements background_process_dispatcher_info().
background_process_cron Implements hook_cron().
background_process_cron_queue_info Implements hook_cron_queue_info().
background_process_cron_queue_worker
background_process_cron_schedule_alter Implements hook_schedule_alter().
background_process_current_clients
background_process_current_handle Get/set current handle.
background_process_get_dispatchers
background_process_get_process Get background process
background_process_get_service_groups Get service hosts defined in the system.
background_process_get_service_hosts Get service hosts defined in the system.
background_process_get_service_host_options
background_process_get_service_host_title
background_process_invoke_dispatcher
background_process_keepalive Keep the current background process alive (meaning restart it when it exits)
background_process_load Load a background process
background_process_menu Implements hook_menu().
background_process_permission Implements hook_permission().
background_process_prepare_dispatcher_callback
background_process_queue Start background process
background_process_queue_locked Queue locked background process
background_process_restart Restart the current background process
background_process_service_access Access handler for service call
background_process_service_group Implements hook_service_group().
background_process_service_group_idle Load balancing based on most idle clients.
background_process_service_group_random Load balancing based on random pick.
background_process_service_group_round_robin Round-robin load balancing based on random pick.
background_process_service_start Call the function requested by the service call
background_process_service_unlock Unlock background process.
background_process_start Start background process
background_process_start_locked Start locked background process
background_process_update_status Update background process status
background_process_watchdog Implements hook_watchdog().
_background_process_callback_name Get string name of callback.

Constants