Overview

Packages

  • currencysymbol
  • MAbout
  • Mage
    • Admin
    • Adminhtml
    • AdminNotification
    • Api
    • Api2
    • Authorizenet
    • Backup
    • Bundle
    • Captcha
    • Catalog
    • CatalogIndex
    • CatalogInventory
    • CatalogRule
    • CatalogSearch
    • Centinel
    • Checkout
    • Cms
    • Compiler
    • Connect
    • Contacts
    • Core
    • Cron
    • CurrencySymbol
    • Customer
    • Dataflow
    • Directory
    • DirtectPost
    • Downloadable
    • Eav
    • GiftMessage
    • GoogleAnalytics
    • GoogleBase
    • GoogleCheckout
    • ImportExport
    • Index
    • Install
    • Log
    • Media
    • Newsletter
    • Oauth
    • Page
    • PageCache
    • Paygate
    • Payment
    • Paypal
    • PaypalUk
    • Persistent
    • Poll
    • ProductAlert
    • Rating
    • Reports
    • Review
    • Rss
    • Rule
    • Sales
    • SalesRule
    • Sedfriend
    • Sendfriend
    • Shipping
    • Sitemap
    • Tag
    • Tax
    • Usa
    • Weee
    • Widget
    • Wishlist
    • XmlConnect
  • None
  • Phoenix
    • Moneybookers
  • PHP
  • Zend
    • Date
    • Mime
    • XmlRpc

Classes

  • Mage_Cron_Helper_Data
  • Mage_Cron_Model_Mysql4_Schedule
  • Mage_Cron_Model_Mysql4_Schedule_Collection
  • Mage_Cron_Model_Observer
  • Mage_Cron_Model_Resource_Schedule
  • Mage_Cron_Model_Resource_Schedule_Collection
  • Mage_Cron_Model_Schedule

Exceptions

  • Mage_Cron_Exception
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Magento
  4:  *
  5:  * NOTICE OF LICENSE
  6:  *
  7:  * This source file is subject to the Open Software License (OSL 3.0)
  8:  * that is bundled with this package in the file LICENSE.txt.
  9:  * It is also available through the world-wide-web at this URL:
 10:  * http://opensource.org/licenses/osl-3.0.php
 11:  * If you did not receive a copy of the license and are unable to
 12:  * obtain it through the world-wide-web, please send an email
 13:  * to license@magentocommerce.com so we can send you a copy immediately.
 14:  *
 15:  * DISCLAIMER
 16:  *
 17:  * Do not edit or add to this file if you wish to upgrade Magento to newer
 18:  * versions in the future. If you wish to customize Magento for your
 19:  * needs please refer to http://www.magentocommerce.com for more information.
 20:  *
 21:  * @category    Mage
 22:  * @package     Mage_Cron
 23:  * @copyright   Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
 24:  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 25:  */
 26: 
 27: /**
 28:  * Crontab observer
 29:  *
 30:  * @category    Mage
 31:  * @package     Mage_Cron
 32:  * @author      Magento Core Team <core@magentocommerce.com>
 33:  */
 34: class Mage_Cron_Model_Observer
 35: {
 36:     const CACHE_KEY_LAST_SCHEDULE_GENERATE_AT   = 'cron_last_schedule_generate_at';
 37:     const CACHE_KEY_LAST_HISTORY_CLEANUP_AT     = 'cron_last_history_cleanup_at';
 38: 
 39:     const XML_PATH_SCHEDULE_GENERATE_EVERY  = 'system/cron/schedule_generate_every';
 40:     const XML_PATH_SCHEDULE_AHEAD_FOR       = 'system/cron/schedule_ahead_for';
 41:     const XML_PATH_SCHEDULE_LIFETIME        = 'system/cron/schedule_lifetime';
 42:     const XML_PATH_HISTORY_CLEANUP_EVERY    = 'system/cron/history_cleanup_every';
 43:     const XML_PATH_HISTORY_SUCCESS          = 'system/cron/history_success_lifetime';
 44:     const XML_PATH_HISTORY_FAILURE          = 'system/cron/history_failure_lifetime';
 45: 
 46:     const REGEX_RUN_MODEL = '#^([a-z0-9_]+/[a-z0-9_]+)::([a-z0-9_]+)$#i';
 47: 
 48:     protected $_pendingSchedules;
 49: 
 50:     /**
 51:      * Process cron queue
 52:      * Geterate tasks schedule
 53:      * Cleanup tasks schedule
 54:      *
 55:      * @param Varien_Event_Observer $observer
 56:      */
 57:     public function dispatch($observer)
 58:     {
 59:         $schedules = $this->getPendingSchedules();
 60:         $scheduleLifetime = Mage::getStoreConfig(self::XML_PATH_SCHEDULE_LIFETIME) * 60;
 61:         $now = time();
 62:         $jobsRoot = Mage::getConfig()->getNode('crontab/jobs');
 63:         $defaultJobsRoot = Mage::getConfig()->getNode('default/crontab/jobs');
 64: 
 65:         foreach ($schedules->getIterator() as $schedule) {
 66:             $jobConfig = $jobsRoot->{$schedule->getJobCode()};
 67:             if (!$jobConfig || !$jobConfig->run) {
 68:                 $jobConfig = $defaultJobsRoot->{$schedule->getJobCode()};
 69:                 if (!$jobConfig || !$jobConfig->run) {
 70:                     continue;
 71:                 }
 72:             }
 73: 
 74:             $runConfig = $jobConfig->run;
 75:             $time = strtotime($schedule->getScheduledAt());
 76:             if ($time > $now) {
 77:                 continue;
 78:             }
 79:             try {
 80:                 $errorStatus = Mage_Cron_Model_Schedule::STATUS_ERROR;
 81:                 $errorMessage = Mage::helper('cron')->__('Unknown error.');
 82: 
 83:                 if ($time < $now - $scheduleLifetime) {
 84:                     $errorStatus = Mage_Cron_Model_Schedule::STATUS_MISSED;
 85:                     Mage::throwException(Mage::helper('cron')->__('Too late for the schedule.'));
 86:                 }
 87: 
 88:                 if ($runConfig->model) {
 89:                     if (!preg_match(self::REGEX_RUN_MODEL, (string)$runConfig->model, $run)) {
 90:                         Mage::throwException(Mage::helper('cron')->__('Invalid model/method definition, expecting "model/class::method".'));
 91:                     }
 92:                     if (!($model = Mage::getModel($run[1])) || !method_exists($model, $run[2])) {
 93:                         Mage::throwException(Mage::helper('cron')->__('Invalid callback: %s::%s does not exist', $run[1], $run[2]));
 94:                     }
 95:                     $callback = array($model, $run[2]);
 96:                     $arguments = array($schedule);
 97:                 }
 98:                 if (empty($callback)) {
 99:                     Mage::throwException(Mage::helper('cron')->__('No callbacks found'));
100:                 }
101: 
102:                 if (!$schedule->tryLockJob()) {
103:                     // another cron started this job intermittently, so skip it
104:                     continue;
105:                 }
106:                 /**
107:                     though running status is set in tryLockJob we must set it here because the object
108:                     was loaded with a pending status and will set it back to pending if we don't set it here
109:                  */
110:                 $schedule
111:                     ->setStatus(Mage_Cron_Model_Schedule::STATUS_RUNNING)
112:                     ->setExecutedAt(strftime('%Y-%m-%d %H:%M:%S', time()))
113:                     ->save();
114: 
115:                 call_user_func_array($callback, $arguments);
116: 
117:                 $schedule
118:                     ->setStatus(Mage_Cron_Model_Schedule::STATUS_SUCCESS)
119:                     ->setFinishedAt(strftime('%Y-%m-%d %H:%M:%S', time()));
120: 
121:             } catch (Exception $e) {
122:                 $schedule->setStatus($errorStatus)
123:                     ->setMessages($e->__toString());
124:             }
125:             $schedule->save();
126:         }
127: 
128:         $this->generate();
129:         $this->cleanup();
130:     }
131: 
132:     public function getPendingSchedules()
133:     {
134:         if (!$this->_pendingSchedules) {
135:             $this->_pendingSchedules = Mage::getModel('cron/schedule')->getCollection()
136:                 ->addFieldToFilter('status', Mage_Cron_Model_Schedule::STATUS_PENDING)
137:                 ->load();
138:         }
139:         return $this->_pendingSchedules;
140:     }
141: 
142:     /**
143:      * Generate cron schedule
144:      *
145:      * @return Mage_Cron_Model_Observer
146:      */
147:     public function generate()
148:     {
149:         /**
150:          * check if schedule generation is needed
151:          */
152:         $lastRun = Mage::app()->loadCache(self::CACHE_KEY_LAST_SCHEDULE_GENERATE_AT);
153:         if ($lastRun > time() - Mage::getStoreConfig(self::XML_PATH_SCHEDULE_GENERATE_EVERY)*60) {
154:             return $this;
155:         }
156: 
157:         $schedules = $this->getPendingSchedules();
158:         $exists = array();
159:         foreach ($schedules->getIterator() as $schedule) {
160:             $exists[$schedule->getJobCode().'/'.$schedule->getScheduledAt()] = 1;
161:         }
162: 
163:         /**
164:          * generate global crontab jobs
165:          */
166:         $config = Mage::getConfig()->getNode('crontab/jobs');
167:         if ($config instanceof Mage_Core_Model_Config_Element) {
168:             $this->_generateJobs($config->children(), $exists);
169:         }
170: 
171:         /**
172:          * generate configurable crontab jobs
173:          */
174:         $config = Mage::getConfig()->getNode('default/crontab/jobs');
175:         if ($config instanceof Mage_Core_Model_Config_Element) {
176:             $this->_generateJobs($config->children(), $exists);
177:         }
178: 
179:         /**
180:          * save time schedules generation was ran with no expiration
181:          */
182:         Mage::app()->saveCache(time(), self::CACHE_KEY_LAST_SCHEDULE_GENERATE_AT, array('crontab'), null);
183: 
184:         return $this;
185:     }
186: 
187:     /**
188:      * Generate jobs for config information
189:      *
190:      * @param   $jobs
191:      * @param   array $exists
192:      * @return  Mage_Cron_Model_Observer
193:      */
194:     protected function _generateJobs($jobs, $exists)
195:     {
196:         $scheduleAheadFor = Mage::getStoreConfig(self::XML_PATH_SCHEDULE_AHEAD_FOR)*60;
197:         $schedule = Mage::getModel('cron/schedule');
198: 
199:         foreach ($jobs as $jobCode => $jobConfig) {
200:             $cronExpr = null;
201:             if ($jobConfig->schedule->config_path) {
202:                 $cronExpr = Mage::getStoreConfig((string)$jobConfig->schedule->config_path);
203:             }
204:             if (empty($cronExpr) && $jobConfig->schedule->cron_expr) {
205:                 $cronExpr = (string)$jobConfig->schedule->cron_expr;
206:             }
207:             if (!$cronExpr) {
208:                 continue;
209:             }
210: 
211:             $now = time();
212:             $timeAhead = $now + $scheduleAheadFor;
213:             $schedule->setJobCode($jobCode)
214:                 ->setCronExpr($cronExpr)
215:                 ->setStatus(Mage_Cron_Model_Schedule::STATUS_PENDING);
216: 
217:             for ($time = $now; $time < $timeAhead; $time += 60) {
218:                 $ts = strftime('%Y-%m-%d %H:%M:00', $time);
219:                 if (!empty($exists[$jobCode.'/'.$ts])) {
220:                     // already scheduled
221:                     continue;
222:                 }
223:                 if (!$schedule->trySchedule($time)) {
224:                     // time does not match cron expression
225:                     continue;
226:                 }
227:                 $schedule->unsScheduleId()->save();
228:             }
229:         }
230:         return $this;
231:     }
232: 
233:     public function cleanup()
234:     {
235:         // check if history cleanup is needed
236:         $lastCleanup = Mage::app()->loadCache(self::CACHE_KEY_LAST_HISTORY_CLEANUP_AT);
237:         if ($lastCleanup > time() - Mage::getStoreConfig(self::XML_PATH_HISTORY_CLEANUP_EVERY)*60) {
238:             return $this;
239:         }
240: 
241:         $history = Mage::getModel('cron/schedule')->getCollection()
242:             ->addFieldToFilter('status', array('in'=>array(
243:                 Mage_Cron_Model_Schedule::STATUS_SUCCESS,
244:                 Mage_Cron_Model_Schedule::STATUS_MISSED,
245:                 Mage_Cron_Model_Schedule::STATUS_ERROR,
246:             )))->load();
247: 
248:         $historyLifetimes = array(
249:             Mage_Cron_Model_Schedule::STATUS_SUCCESS => Mage::getStoreConfig(self::XML_PATH_HISTORY_SUCCESS)*60,
250:             Mage_Cron_Model_Schedule::STATUS_MISSED => Mage::getStoreConfig(self::XML_PATH_HISTORY_FAILURE)*60,
251:             Mage_Cron_Model_Schedule::STATUS_ERROR => Mage::getStoreConfig(self::XML_PATH_HISTORY_FAILURE)*60,
252:         );
253: 
254:         $now = time();
255:         foreach ($history->getIterator() as $record) {
256:             if (strtotime($record->getExecutedAt()) < $now-$historyLifetimes[$record->getStatus()]) {
257:                 $record->delete();
258:             }
259:         }
260: 
261:         // save time history cleanup was ran with no expiration
262:         Mage::app()->saveCache(time(), self::CACHE_KEY_LAST_HISTORY_CLEANUP_AT, array('crontab'), null);
263: 
264:         return $this;
265:     }
266: }
267: 
Magento 1.7.0.2 API documentation generated by ApiGen 2.8.0