phpDocumentor pond
[ class tree: pond ] [ index: pond ] [ all elements ]

Source for file cron_exec.php

Documentation is available at cron_exec.php

  1. <?php
  2. /**
  3.  * Execute cron jobs.
  4.  *
  5.  * Example to use CLI:
  6.  * >c:\php4\php cron_exec.php
  7.  * >c:\php4\php-cli cron_exec.php
  8.  *
  9.  * @package pond
  10.  */
  11.  
  12.  
  13. /**
  14.  * Include config
  15.  */
  16. require_once dirname(__FILE__).'/../qp_config/_config.php';
  17.  
  18. $no_session true;
  19. require_once $inc_path .'_main.inc.php';
  20.  
  21. /**
  22.  * Cron support functions
  23.  */
  24. load_funcs'/cron/_cron.funcs.php' );
  25.  
  26. /**
  27.  * @global integer Quietness.
  28.  *          1 suppresses trivial/informative messages,
  29.  *          2 suppresses success messages,
  30.  *          3 suppresses errors.
  31.  */
  32. $quiet 0;
  33. if$is_cli )
  34. // called through Command Line Interface, handle args:
  35.  
  36.     ifisset$_SERVER['argc']$_SERVER['argv') )
  37.     {
  38.         $argc $_SERVER['argc'];
  39.         $argv $_SERVER['argv'];
  40.     }
  41.  
  42.     ifisset($argv) )
  43.     // may not be set for CGI
  44.         foreacharray_slice($argv1as $v )
  45.         {
  46.             switch$v )
  47.             {
  48.                 case '-h':
  49.                 case '--help':
  50.                     // display help:
  51.                     echo $argv[0]' - Execute cron jobs for '$app_name"\n";
  52.                     echo "\n";
  53.                     echo "Options:\n";
  54.                     echo " -q --quiet: Be quiet (do not output a message, if there are no jobs).\n";
  55.                     echo "             This is especially useful, when running as a cron job.\n";
  56.                     echo "             You can use this up to three times to increase quietness.\n";
  57.                     echo "             Successful runs can be made silent with \"-q -q\".\n";
  58.                     exit(0);
  59.                     break;
  60.  
  61.                 case '-q':
  62.                 case '--quiet':
  63.                     // increase quietness:
  64.                     $quiet++;
  65.                     break;
  66.  
  67.                 default:
  68.                     echo 'Invalid option "'.$v.'". Use "-h" or "--help" for a list of options.'."\n";
  69.                     die(1);
  70.             }
  71.         }
  72.     }
  73. }
  74. else
  75. // This is a web request:
  76.     ?>
  77.     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  78.     <html>
  79.     <head>
  80.         <title>Cron exec</title>
  81.         <link rel="stylesheet" type="text/css" href="<?php echo $rsc_url ?>css/basic.css">
  82.     </head>
  83.     <body>
  84.         <h1>Cron exec</h1>
  85.         <p>This script will execute the next task in the cron queue.
  86.         You should normally call it with the CLI (command line interface) version of PHP
  87.         and automate that call through a cron.</p>
  88.     <?php
  89. }
  90.  
  91. /*
  92.  * The following will feel a little bloated...
  93.  * BUT it is actually a pretty nifty design to prevent double execution of tasks without any transaction!
  94.  * The trick is to rely on the primary key of the cron__log table.
  95.  */
  96.  
  97. // Get next task to run in queue which has not started execution yet:
  98. $sql 'SELECT *
  99.                     FROM T_cron__task LEFT JOIN T_cron__log ON ctsk_ID = clog_ctsk_ID
  100.                  WHERE clog_ctsk_ID IS NULL
  101.                      AND ctsk_start_datetime <= '.$DB->quotedate2mysql($localtimenow) ).'
  102.                  ORDER BY ctsk_start_datetime ASC, ctsk_ID ASC
  103.                  LIMIT 1';
  104. $task $DB->get_row$sqlOBJECT0'Get next task to run in queue which has not started execution yet' );
  105.  
  106. ifempty$task ) )
  107. {
  108.     cron_log'There is no task to execute yet.');
  109. }
  110. else
  111. {
  112.     $ctsk_ID $task->ctsk_ID;
  113.     $ctsk_name $task->ctsk_name;
  114.  
  115.     cron_log'Requesting lock on task #'.$ctsk_ID.' ['.$ctsk_name.']');
  116.  
  117.     $DB->halt_on_error false;
  118.     $DB->show_errors false;
  119.     $sql 'INSERT INTO T_cron__log( clog_ctsk_ID, clog_realstart_datetime, clog_status)
  120.                     VALUES( '.$ctsk_ID.', '.$DB->quotedate2mysql($localtimenow) ).', "started" )';
  121.     // Duplicate query for tests!
  122.     // $DB->query( $sql, 'Request lock' );
  123.     if$DB->query$sql'Request lock' != )
  124.     // This has no affected exactly ONE row: error! (probably locked -- duplicate key -- by a concurrent process)
  125.         $DB->show_errors true;
  126.         $DB->halt_on_error true;
  127.         cron_log'Could not lock. Task is probably handled by another process.');
  128.     }
  129.     else
  130.     {
  131.         if!empty$task->ctsk_repeat_after ) )
  132.         {    // This task wants to be repeated:
  133.             // Note: we use the current time for 2 reasons: 1) prevent scheduling something in the past AND 2) introduce variety so that everyone doesn't run his repeated tasks at the same exact time, especially pings, pollings...
  134.             $new_start_datetime $localtimenow $task->ctsk_repeat_after;
  135.             $sql 'INSERT INTO T_cron__task( ctsk_start_datetime, ctsk_repeat_after, ctsk_name, ctsk_controller, ctsk_params )
  136.                             VALUES( '.$DB->quote(date2mysql($new_start_datetime)).', '.$DB->quote($task->ctsk_repeat_after).', '
  137.                                                 .$DB->quote($ctsk_name).', '.$DB->quote($task->ctsk_controller).', '.$DB->quote($task->ctsk_params).' )';
  138.             $DB->query$sql'Schedule repeated task.' );
  139.         }
  140.  
  141.         $DB->show_errors true;
  142.         $DB->halt_on_error true;
  143.         cron_log'Starting task #'.$ctsk_ID.' ['.$ctsk_name.'] at '.date'H:i:s'$localtimenow ).'.');
  144.  
  145.         ifempty($task->ctsk_params) )
  146.         {
  147.             $cron_params array();
  148.         }
  149.         else
  150.         {
  151.             $cron_params unserialize$task->ctsk_params );
  152.         }
  153.  
  154.         // The job may need to know its ID (to set logical locks for example):
  155.         $cron_params['ctsk_ID'$ctsk_ID;
  156.  
  157.         // EXECUTE
  158.         call_job$task->ctsk_controller$cron_params );
  159.  
  160.         // Record task as finished:
  161.         ifempty($timestop) )
  162.         {
  163.             $timestop time($time_difference;
  164.         }
  165.         $sql ' UPDATE T_cron__log
  166.                                 SET clog_status = '.$DB->quote($result_status).',
  167.                                         clog_realstop_datetime = '.$DB->quotedate2mysql($timestop) ).',
  168.                                         clog_messages = '.$DB->quote($result_message/* May be NULL */.'
  169.                             WHERE clog_ctsk_ID = '.$ctsk_ID;
  170.         $DB->query$sql'Record task as finished.' );
  171.     }
  172. }
  173.  
  174. // Detect timed out tasks:
  175. $sql ' UPDATE T_cron__log
  176.                         SET clog_status = "timeout"
  177.                     WHERE clog_status = "started"
  178.                                 AND clog_realstart_datetime < '.$DB->quotedate2mysqltime($time_difference $cron_timeout_delay ) );
  179. $DB->query$sql'Detect cron timeouts.' );
  180.  
  181.  
  182.  
  183. if$is_cli )
  184. // This is a web request:
  185.     echo '<p><a href="cron_exec.php">Refresh Now!</a></p>';
  186.     echo '<p>This page should refresh automatically in 15 seconds...</p>';
  187.     echo '<!-- This is invalid HTML but it is SOOOOOO helpful! (Delay will be triggered when we reach that point -->';
  188.     echo '<meta http-equiv="Refresh" content="15" />';
  189.     ?>
  190.     </body>
  191.     </html>
  192.     <?php
  193. }
  194.  
  195. ?>