Commit c54d442d authored by Michael Oehlhof's avatar Michael Oehlhof Committed by Christian Kuhn
Browse files

[FEATURE] EXT:Scheduler: Run manually executed tasks on next cron-run

Added a feature to the scheduler to mark tasks to be run by
next cron job.

Resolves: #45537
Releases: master
Change-Id: I72d0e693821630a0be655159b53c168b1973d886
Reviewed-on: https://review.typo3.org/45807

Tested-by: default avatarTYPO3com <no-reply@typo3.com>
Reviewed-by: Philipp Gampe's avatarPhilipp Gampe <philipp.gampe@typo3.org>
Tested-by: Philipp Gampe's avatarPhilipp Gampe <philipp.gampe@typo3.org>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent 9b1bcbf8
......@@ -2470,6 +2470,12 @@ class IconRegistry implements SingletonInterface
'name' => 'play-circle',
]
],
'extensions-scheduler-run-task-cron' => [
'provider' => FontawesomeIconProvider::class,
'options' => [
'name' => 'play-circle-o',
]
],
'extensions-workspaces-generatepreviewlink' => [
'provider' => BitmapIconProvider::class,
'options' => [
......
.. include:: ../../Includes.txt
==============================================================
Feature: #45537 - Run manually executed tasks on next cron-run
==============================================================
See :issue:`45537`
Description
===========
There is a new action icon to mark a task to be run by cron.
Also a new button "Execute selected tasks on next cron job"
was added to mark all selected actions to be run by next cron job.
.. index:: Backend
\ No newline at end of file
......@@ -272,6 +272,10 @@ class SchedulerModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClas
$this->toggleDisableAction();
$content .= $this->listTasksAction();
break;
case 'setNextExecutionTime':
$this->setNextExecutionTimeAction();
$content .= $this->listTasksAction();
break;
case 'list':
default:
......@@ -502,6 +506,18 @@ class SchedulerModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClas
$task->save();
}
/**
* Sets the next execution time of the submitted task to now
*
* @return void
*/
protected function setNextExecutionTimeAction()
{
$task = $this->scheduler->fetchTask($this->submittedData['uid']);
$task->setRunOnNextCronJob(true);
$task->save();
}
/**
* Return a form to add a new task or edit an existing one
*
......@@ -818,17 +834,22 @@ class SchedulerModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClas
$task = $this->scheduler->fetchTask($uid);
$class = get_class($task);
$name = $registeredClasses[$class]['title'] . ' (' . $registeredClasses[$class]['extension'] . ')';
// Now try to execute it and report on outcome
try {
$result = $this->scheduler->executeTask($task);
if ($result) {
$this->addMessage(sprintf($this->getLanguageService()->getLL('msg.executed'), $name));
} else {
$this->addMessage(sprintf($this->getLanguageService()->getLL('msg.notExecuted'), $name), FlashMessage::ERROR);
if (GeneralUtility::_POST('go_cron') !== null) {
$task->setRunOnNextCronJob(true);
$task->save();
} else {
// Now try to execute it and report on outcome
try {
$result = $this->scheduler->executeTask($task);
if ($result) {
$this->addMessage(sprintf($this->getLanguageService()->getLL('msg.executed'), $name));
} else {
$this->addMessage(sprintf($this->getLanguageService()->getLL('msg.notExecuted'), $name), FlashMessage::ERROR);
}
} catch (\Exception $e) {
// An exception was thrown, display its message as an error
$this->addMessage(sprintf($this->getLanguageService()->getLL('msg.executionFailed'), $name, $e->getMessage()), FlashMessage::ERROR);
}
} catch (\Exception $e) {
// An exception was thrown, display its message as an error
$this->addMessage(sprintf($this->getLanguageService()->getLL('msg.executionFailed'), $name, $e->getMessage()), FlashMessage::ERROR);
}
} catch (\OutOfBoundsException $e) {
$this->addMessage(sprintf($this->getLanguageService()->getLL('msg.taskNotFound'), $uid), FlashMessage::ERROR);
......@@ -962,6 +983,8 @@ class SchedulerModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClas
$this->moduleTemplate->getIconFactory()->getIcon('actions-document-close', Icon::SIZE_SMALL)->render() . '</a>';
$runAction = '<a class="btn btn-default" href="' . htmlspecialchars($this->moduleUri . '&tx_scheduler[execute][]=' . $schedulerRecord['uid']) . '" title="' . htmlspecialchars($this->getLanguageService()->getLL('action.run_task')) . '" class="icon">' .
$this->moduleTemplate->getIconFactory()->getIcon('extensions-scheduler-run-task', Icon::SIZE_SMALL)->render() . '</a>';
$runCronAction = '<a class="btn btn-default" href="' . htmlspecialchars($this->moduleUri . '&CMD=setNextExecutionTime&tx_scheduler[uid]=' . $schedulerRecord['uid']) . '" title="' . $this->getLanguageService()->getLL('action.run_task_cron', true) . '" class="icon">' .
$this->moduleTemplate->getIconFactory()->getIcon('extensions-scheduler-run-task-cron', Icon::SIZE_SMALL)->render() . '</a>';
// Define some default values
$lastExecution = '-';
......@@ -1061,7 +1084,7 @@ class SchedulerModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClas
if ($isRunning) {
$actions = '<div class="btn-group" role="group">' . $stopAction . '</div>';
} else {
$actions .= '&nbsp;<div class="btn-group" role="group">' . $runAction . '</div>';
$actions .= '&nbsp;<div class="btn-group" role="group">' . $runAction . $runCronAction . '</div>';
}
// Check if the last run failed
......@@ -1437,7 +1460,7 @@ class SchedulerModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClas
->setFieldName('');
$buttonBar->addButton($helpButton);
// Add and Reload
if (empty($this->CMD) || $this->CMD === 'list' || $this->CMD === 'delete' || $this->CMD === 'stop' || $this->CMD === 'toggleHidden') {
if (empty($this->CMD) || $this->CMD === 'list' || $this->CMD === 'delete' || $this->CMD === 'stop' || $this->CMD === 'toggleHidden' || $this->CMD === 'setNextExecutionTime') {
$reloadButton = $buttonBar->makeLinkButton()
->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.reload'))
->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-refresh', Icon::SIZE_SMALL))
......
......@@ -156,6 +156,7 @@ class Scheduler implements \TYPO3\CMS\Core\SingletonInterface
*/
public function executeTask(Task\AbstractTask $task)
{
$task->setRunOnNextCronJob(false);
// Trigger the saving of the task, as this will calculate its next execution time
// This should be calculated all the time, even if the execution is skipped
// (in case it is skipped, this pushes back execution to the next possible date)
......@@ -254,7 +255,11 @@ class Scheduler implements \TYPO3\CMS\Core\SingletonInterface
$taskUid = $task->getTaskUid();
if (!empty($taskUid)) {
try {
$executionTime = $task->getNextDueExecution();
if ($task->getRunOnNextCronJob()) {
$executionTime = time();
} else {
$executionTime = $task->getNextDueExecution();
}
$task->setExecutionTime($executionTime);
} catch (\Exception $e) {
$task->setDisabled(true);
......
......@@ -49,6 +49,13 @@ abstract class AbstractTask
*/
protected $disabled = false;
/**
* Run on next cron job flag, TRUE if task should run on next cronjob, FALSE otherwise
*
* @var bool
*/
protected $runOnNextCronJob = false;
/**
* The execution object related to the task
*
......@@ -186,6 +193,26 @@ abstract class AbstractTask
}
}
/**
* This method set the flag for next cron job execution
*
* @param bool $flag TRUE if task should run with the next cron job, FALSE otherwise
*/
public function setRunOnNextCronJob($flag)
{
$this->runOnNextCronJob = $flag;
}
/**
* This method returns the run on next cron job status of the task
*
* @return bool TRUE if task should run on next cron job, FALSE otherwise
*/
public function getRunOnNextCronJob()
{
return $this->runOnNextCronJob;
}
/**
* This method is used to set the timestamp corresponding to the next execution time of the task
*
......
......@@ -96,7 +96,7 @@ following:
coming from and any additional information specific to the task (for
example, the e-mail to which the "test" task will send a message or
the sleep duration of the "sleep" task). It also show a summary of the
task's status, as a bullet. More details below.
task's status with an icon.
- The fifth column shows whether the task is recurring or will run only
a single time.
......@@ -120,9 +120,8 @@ following:
Note that all dates and times are displayed in the server's time zone.
The server time appears at the bottom of the screen.
At the bottom of the screen is a link to add a new task and a legend
explaining the various states shown in the tasks list. This is pretty
much self-explanatory. If there are a lot of tasks that appear late,
At the top of the screen is a link to add a new task.
If there are a lot of tasks that appear late,
consider changing the frequency at which the cron job is running (see
"Choosing a frequency" above).
......
.. ==================================================
.. FOR YOUR INFORMATION
.. --------------------------------------------------
.. -*- coding: utf-8 -*- with BOM.
.. include:: ../../Includes.txt
.. _executing-a-task-on-next-cronjob:
Executing a task on next cron job
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It is possible to manually set the next execution time of one or more
registered tasks from the BE module to the current time.
The selected tasks will then be running on the next cron job.
......@@ -28,4 +28,5 @@ one for actually managing the tasks.
GroupTask/Index
StopTask/Index
ManualExecution/Index
ExecuteNextCronjob/Index
......@@ -66,6 +66,9 @@
<trans-unit id="label.executeSelected">
<source>Execute selected tasks</source>
</trans-unit>
<trans-unit id="label.cronjobSelected">
<source>Execute selected tasks on next cron job</source>
</trans-unit>
<trans-unit id="label.extension">
<source>Extension</source>
</trans-unit>
......@@ -333,6 +336,9 @@
<trans-unit id="action.run_task">
<source>Run task</source>
</trans-unit>
<trans-unit id="action.run_task_cron">
<source>Run task on next cron job</source>
</trans-unit>
<trans-unit id="testTask.name">
<source>Scheduler test task</source>
</trans-unit>
......
......@@ -2,5 +2,8 @@
<button class="btn btn-default" name="go" id="scheduler_executeselected">
<f:translate key="label.executeSelected" />
</button>
<button class="btn btn-default" name="go_cron" id="scheduler_executeselected">
<f:translate key="label.cronjobSelected" />
</button>
<f:render partial="ServerTime" arguments="{now: now}" />
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment