Index: mod1/index.php =================================================================== --- mod1/index.php (revision 1121) +++ mod1/index.php (working copy) @@ -796,6 +796,7 @@ $task = $task = unserialize($schedulerRecord['serialized_task_object']); $task->setScheduler(); $executionStatus = 'stopped'; + $executionStatusDetail = ''; $cridParts = self::extractCridInformation($schedulerRecord['crid']); $name = $registeredClasses[$cridParts['class']]['title']. ' (' . $registeredClasses[$cridParts['class']]['extension'] . ')'; @@ -860,8 +861,18 @@ $executionStatus = 'disabled'; } + // a failure is the worst thing that could happen, so it must overwrite all other statuses + if (!empty($schedulerRecord['lastexecution_failure'])) { + $exception = unserialize($schedulerRecord['lastexecution_failure']); + $this->addMessage($exception->getMessage(), 3); + + $executionStatus = 'failure'; + $executionStatusDetail = 'Execution failed: ' . $exception->getCode() . ', ' . $exception->getMessage(); + } + + // Format the execution status - $executionStatus = '' . $GLOBALS['LANG']->getLL('status.' . $executionStatus) . ''; + $executionStatus = '' . $GLOBALS['LANG']->getLL('status.' . $executionStatus) . ''; $table[$tr][] = $startExecutionElement; $table[$tr][] = $actions; @@ -889,10 +900,11 @@ $content .= '

' . $GLOBALS['LANG']->getLL('status.legend') . ':

'; Index: mod1/locallang.xml =================================================================== --- mod1/locallang.xml (revision 1121) +++ mod1/locallang.xml (working copy) @@ -89,10 +89,12 @@ + + Index: class.tx_scheduler_task.php =================================================================== --- class.tx_scheduler_task.php (revision 1121) +++ class.tx_scheduler_task.php (working copy) @@ -121,8 +121,9 @@ * It MUST be implemented by all classes inheriting from this one * Note that there is no error handling, errors and failures are expected * to be handled and logged by the client implementations. + * Should return true on successful execution, false on error. * - * @return void + * @return boolean Returns true on successful execution, false on error */ abstract public function execute(); @@ -427,10 +428,11 @@ /** * Removes given execution from list * - * @param integer $executionID: id of the execution to remove + * @param integer Id of the execution to remove. + * @param Exception An exception to signal a failed execution * @return void */ - public function unmarkExecution($executionID) { + public function unmarkExecution($executionID, Exception $failure = null) { // Get the executions for the task $queryArr = array( 'SELECT' => 'serialized_executions', @@ -452,11 +454,34 @@ } else { $runningExecutionsSerialized = ''; } + + if ($failure instanceof Exception) { + // Log failed execution + $GLOBALS['BE_USER']->writelog( + 4, + 0, + 1, + $failure->getCode(), + '[scheduler]: Task failed to execute successfully. CRID: ' + . $this->crid . ', UID: ' + . $this->taskUid . '. ' + . $failure->getMessage(), + array() + ); + + $failure = serialize($failure); + } else { + $failure = ''; + } + // Save the updated executions list $GLOBALS['TYPO3_DB']->exec_UPDATEquery( 'tx_scheduler_task', 'uid = ' . intval($this->taskUid), - array('serialized_executions' => $runningExecutionsSerialized) + array( + 'serialized_executions' => $runningExecutionsSerialized, + 'lastexecution_failure' => $failure + ) ); } } Index: ext_autoload.php =================================================================== --- ext_autoload.php (revision 1121) +++ ext_autoload.php (working copy) @@ -6,13 +6,14 @@ */ // TODO: document necessity of providing autoloader information return array( - 'tx_scheduler' => t3lib_extMgm::extPath('scheduler', 'class.tx_scheduler.php'), - 'tx_scheduler_croncmd' => t3lib_extMgm::extPath('scheduler', 'class.tx_scheduler_croncmd.php'), - 'tx_scheduler_task' => t3lib_extMgm::extPath('scheduler', 'class.tx_scheduler_task.php'), - 'tx_scheduler_execution' => t3lib_extMgm::extPath('scheduler', 'class.tx_scheduler_execution.php'), - 'tx_scheduler_testtask' => t3lib_extMgm::extPath('scheduler', 'examples/class.tx_scheduler_testtask.php'), - 'tx_scheduler_testtaskhook' => t3lib_extMgm::extPath('scheduler', 'examples/class.tx_scheduler_testtaskhook.php'), - 'tx_scheduler_sleeptask' => t3lib_extMgm::extPath('scheduler', 'examples/class.tx_scheduler_sleeptask.php'), - 'tx_scheduler_sleeptaskhook' => t3lib_extMgm::extPath('scheduler', 'examples/class.tx_scheduler_sleeptaskhook.php') + 'tx_scheduler' => t3lib_extMgm::extPath('scheduler', 'class.tx_scheduler.php'), + 'tx_scheduler_croncmd' => t3lib_extMgm::extPath('scheduler', 'class.tx_scheduler_croncmd.php'), + 'tx_scheduler_task' => t3lib_extMgm::extPath('scheduler', 'class.tx_scheduler_task.php'), + 'tx_scheduler_execution' => t3lib_extMgm::extPath('scheduler', 'class.tx_scheduler_execution.php'), + 'tx_scheduler_failedexecutionexception' => t3lib_extMgm::extPath('scheduler', 'class.tx_scheduler_failedexecutionexception.php'), + 'tx_scheduler_testtask' => t3lib_extMgm::extPath('scheduler', 'examples/class.tx_scheduler_testtask.php'), + 'tx_scheduler_testtaskhook' => t3lib_extMgm::extPath('scheduler', 'examples/class.tx_scheduler_testtaskhook.php'), + 'tx_scheduler_sleeptask' => t3lib_extMgm::extPath('scheduler', 'examples/class.tx_scheduler_sleeptask.php'), + 'tx_scheduler_sleeptaskhook' => t3lib_extMgm::extPath('scheduler', 'examples/class.tx_scheduler_sleeptaskhook.php') ); ?> Index: ext_tables.sql =================================================================== --- ext_tables.sql (revision 1121) +++ ext_tables.sql (working copy) @@ -8,6 +8,7 @@ crid varchar(255) DEFAULT '' NOT NULL, nextexecution int(11) unsigned DEFAULT '0' NOT NULL, lastexecution_time int(11) unsigned DEFAULT '0' NOT NULL, + lastexecution_failure text NOT NULL, lastexecution_context char(3) DEFAULT '' NOT NULL, serialized_task_object text NOT NULL, serialized_executions text NOT NULL, Index: examples/class.tx_scheduler_sleeptask.php =================================================================== --- examples/class.tx_scheduler_sleeptask.php (revision 1121) +++ examples/class.tx_scheduler_sleeptask.php (working copy) @@ -55,6 +55,8 @@ } sleep($time); + + return true; } } Index: examples/class.tx_scheduler_testtask.php =================================================================== --- examples/class.tx_scheduler_testtask.php (revision 1121) +++ examples/class.tx_scheduler_testtask.php (working copy) @@ -49,6 +49,7 @@ * @return void */ public function execute() { + $success = false; if (!empty($this->email)) { // If an email address is defined, send a message to it @@ -100,11 +101,13 @@ $mailer->setRecipient($this->email); $mailer->setHeaders(); $mailer->setContent(); - $mailer->sendtheMail(); + $success = $mailer->sendtheMail(); } else { // No email defined, just log the task t3lib_div::devLog('[tx_scheduler_testtask]: No email address given', 'scheduler', 2); } + + return $success; } } Index: class.tx_scheduler.php =================================================================== --- class.tx_scheduler.php (revision 1121) +++ class.tx_scheduler.php (working copy) @@ -202,11 +202,23 @@ // Register execution $executionID = $task->markExecution(); - // Execute task - $task->execute(); + $failure = null; + try { + // Execute task + $successfullyExecuted = $task->execute(); + + if (!$successfullyExecuted) { + throw new tx_scheduler_FailedExecutionException( + 'Task failed to execute successfully. CRID: ' . $task->getCrid() . ', UID: ' . $task->getTaskUid(), + 1250596541 + ); + } + } catch(Exception $e) { + $failure = $e; + } // Unregister excution - $task->unmarkExecution($executionID); + $task->unmarkExecution($executionID, $failure); // Log completion of execution $GLOBALS['BE_USER']->writelog( Index: class.tx_scheduler_failedexecutionexception.php =================================================================== --- class.tx_scheduler_failedexecutionexception.php (revision 0) +++ class.tx_scheduler_failedexecutionexception.php (revision 0) @@ -0,0 +1,43 @@ + +* All rights reserved +* +* This script is part of the TYPO3 project. The TYPO3 project is +* free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* The GNU General Public License can be found at +* http://www.gnu.org/copyleft/gpl.html. +* +* This script is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* This copyright notice MUST APPEAR in all copies of the script! +***************************************************************/ + + +/** + * Failed execution exception + * + * @author Ingo Renner + * @package TYPO3 + * @subpackage scheduler + */ +class tx_scheduler_FailedExecutionException extends RuntimeException { + + +} + + +if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/scheduler/class.tx_scheduler_failedexecutionexception.php']) { + include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/scheduler/class.tx_scheduler_failedexecutionexception.php']); +} + +?> \ No newline at end of file