feat: scheduler runs the imports and the housekeeping tasks again
typo3/cms-scheduler 13.4 replaces the three direct cron jobs with one scheduler:run cron job. ep:scheduler-tasks (one-off, idempotent) soft-deletes the TYPO3 10 tasks TYPO3 13 cannot run (import task classes that are gone, one groups.swiss task per house with the API keys in the database, the retired E&P Events log) and adds "Execute console commands" tasks for ep:import-dates, ep:import-snowreport and ep:groups-swiss with the TYPO3 10 schedules. The core garbage collection, IP anonymization and file indexing tasks keep working as they are; tx_epproducts_log is registered for garbage collection again. The first execution is the next cron match, so adding the tasks never starts an import or a groups.swiss export right away. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
f193d356cb
commit
520feb003f
5 files changed
+147
-1
No files matched your search
@@ -42,6 +42,7 @@
|
|||||||
"typo3/cms-recycler": "^13.4",
|
"typo3/cms-recycler": "^13.4",
|
||||||
"typo3/cms-redirects": "^13.4",
|
"typo3/cms-redirects": "^13.4",
|
||||||
"typo3/cms-rte-ckeditor": "^13.4",
|
"typo3/cms-rte-ckeditor": "^13.4",
|
||||||
|
"typo3/cms-scheduler": "^13.4",
|
||||||
"typo3/cms-seo": "^13.4",
|
"typo3/cms-seo": "^13.4",
|
||||||
"typo3/cms-setup": "^13.4",
|
"typo3/cms-setup": "^13.4",
|
||||||
"typo3/cms-sys-note": "^13.4",
|
"typo3/cms-sys-note": "^13.4",
|
||||||
|
|||||||
Generated
+56
-1
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "440f3e580365f1608cf72549ef769104",
|
"content-hash": "85a0f79761fbcaf517b130c2f7a3e114",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "b13/container",
|
"name": "b13/container",
|
||||||
@@ -8180,6 +8180,61 @@
|
|||||||
},
|
},
|
||||||
"time": "2026-10-09T09:26:19+00:00"
|
"time": "2026-10-09T09:26:19+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "typo3/cms-scheduler",
|
||||||
|
"version": "v13.4.36",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/TYPO3-CMS/scheduler.git",
|
||||||
|
"reference": "5e2d1cddedbf479d17eb5f6768fa006895c194e9"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/TYPO3-CMS/scheduler/zipball/5e2d1cddedbf479d17eb5f6768fa006895c194e9",
|
||||||
|
"reference": "5e2d1cddedbf479d17eb5f6768fa006895c194e9",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"typo3/cms-core": "13.4.36"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"typo3/cms": "*"
|
||||||
|
},
|
||||||
|
"type": "typo3-cms-framework",
|
||||||
|
"extra": {
|
||||||
|
"typo3/cms": {
|
||||||
|
"extension-key": "scheduler"
|
||||||
|
},
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "13.4.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"TYPO3\\CMS\\Scheduler\\": "Classes/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"GPL-2.0-or-later"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "TYPO3 Core Team",
|
||||||
|
"email": "[email protected]",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "TYPO3 CMS Scheduler - Schedule tasks to run once or periodically at a specific time.",
|
||||||
|
"homepage": "https://typo3.org",
|
||||||
|
"support": {
|
||||||
|
"chat": "https://typo3.org/help",
|
||||||
|
"docs": "https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us",
|
||||||
|
"issues": "https://forge.typo3.org",
|
||||||
|
"source": "https://github.com/typo3/typo3"
|
||||||
|
},
|
||||||
|
"time": "2026-10-09T09:26:19+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "typo3/cms-seo",
|
"name": "typo3/cms-seo",
|
||||||
"version": "v13.4.36",
|
"version": "v13.4.36",
|
||||||
|
|||||||
@@ -94,6 +94,9 @@ return [
|
|||||||
'showCheckIntegrityInfoInReports' => '1',
|
'showCheckIntegrityInfoInReports' => '1',
|
||||||
'showCheckIntegrityInfoInReportsSeconds' => '86400',
|
'showCheckIntegrityInfoInReportsSeconds' => '86400',
|
||||||
],
|
],
|
||||||
|
'scheduler' => [
|
||||||
|
'maxLifetime' => '1440',
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'FE' => [
|
'FE' => [
|
||||||
'cacheHash' => [
|
'cacheHash' => [
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace EP\EpProducts\Command;
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository;
|
||||||
|
use TYPO3\CMS\Scheduler\Task\ExecuteSchedulableCommandTask;
|
||||||
|
|
||||||
|
#[AsCommand(name: 'ep:scheduler-tasks', description: 'Replaces the TYPO3 10 import tasks with scheduler tasks running the ep:* commands')]
|
||||||
|
class SchedulerTasksCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* TYPO3 10 tasks TYPO3 13 cannot run: 5/10 ImportSnowreportTask/ImportDatesTask (classes gone), 6 ImportContingentsTask
|
||||||
|
* (off since 2026-08), 16-21 one ep:groups-swiss task per house (API keys in the database), 25 garbage collection of
|
||||||
|
* the retired tx_epevents_log. The core housekeeping tasks 13, 14, 22, 23 and 24 work unchanged.
|
||||||
|
*/
|
||||||
|
private const OLD_TASKS = [5, 6, 10, 16, 17, 18, 19, 20, 21, 25];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same schedules and groups as on TYPO3 10 (1 Datenimport, 2 Datenexport); ep:groups-swiss without arguments
|
||||||
|
* exports all houses of groupsSwissHouses in secrets.php.
|
||||||
|
*/
|
||||||
|
private const NEW_TASKS = [
|
||||||
|
['command' => 'ep:import-dates', 'cron' => '*/15 6-20 * * *', 'multiple' => true, 'group' => 1, 'description' => 'Reisedaten aus MyE&P importieren'],
|
||||||
|
['command' => 'ep:import-snowreport', 'cron' => '0 6 * * *', 'multiple' => false, 'group' => 1, 'description' => 'Schneehöhen importieren'],
|
||||||
|
['command' => 'ep:groups-swiss', 'cron' => '0 14 * * *', 'multiple' => false, 'group' => 2, 'description' => 'Belegung der Gruppenhäuser nach groups.swiss exportieren'],
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private readonly SchedulerTaskRepository $taskRepository,
|
||||||
|
private readonly ConnectionPool $connectionPool,
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure(): void
|
||||||
|
{
|
||||||
|
$this->addOption('dry-run', null, InputOption::VALUE_NONE, 'Only show what would change');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$dryRun = (bool)$input->getOption('dry-run');
|
||||||
|
|
||||||
|
$existing = [];
|
||||||
|
foreach ($this->connectionPool->getConnectionForTable('tx_scheduler_task')->select(['uid', 'serialized_task_object'], 'tx_scheduler_task', ['deleted' => 0])->fetchAllAssociative() as $row) {
|
||||||
|
if (in_array((int)$row['uid'], self::OLD_TASKS, true)) {
|
||||||
|
$output->writeln(sprintf('Delete TYPO3 10 task %d', $row['uid']));
|
||||||
|
if (!$dryRun) {
|
||||||
|
$this->taskRepository->remove((int)$row['uid']);
|
||||||
|
}
|
||||||
|
} elseif (preg_match('/s:20:"\0\*\0commandIdentifier";s:\d+:"([^"]+)"/', (string)$row['serialized_task_object'], $matches)) {
|
||||||
|
$existing[$matches[1]] = (int)$row['uid'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (self::NEW_TASKS as $config) {
|
||||||
|
if (isset($existing[$config['command']])) {
|
||||||
|
$output->writeln(sprintf('Task for %s exists (%d)', $config['command'], $existing[$config['command']]));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$output->writeln(sprintf('Add task for %s (%s)', $config['command'], $config['cron']));
|
||||||
|
if ($dryRun) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$task = GeneralUtility::makeInstance(ExecuteSchedulableCommandTask::class);
|
||||||
|
$task->setCommandIdentifier($config['command']);
|
||||||
|
$task->setDescription($config['description']);
|
||||||
|
$task->setTaskGroup($config['group']);
|
||||||
|
$task->registerRecurringExecution($GLOBALS['EXEC_TIME'] - 1, 0, 0, $config['multiple'], $config['cron']);
|
||||||
|
$this->taskRepository->add($task);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,11 @@ $boot = function () {
|
|||||||
// Client-side callers pass these parameters in POST bodies, which cHash never inspects.
|
// Client-side callers pass these parameters in POST bodies, which cHash never inspects.
|
||||||
$GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['requireCacheHashPresenceParameters'][] = '^tx_epproducts_ajax';
|
$GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['requireCacheHashPresenceParameters'][] = '^tx_epproducts_ajax';
|
||||||
|
|
||||||
|
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\TYPO3\CMS\Scheduler\Task\TableGarbageCollectionTask::class]['options']['tables']['tx_epproducts_log'] = [
|
||||||
|
'dateField' => 'time_micro',
|
||||||
|
'expirePeriod' => 180,
|
||||||
|
];
|
||||||
|
|
||||||
ExtensionUtility::configurePlugin(
|
ExtensionUtility::configurePlugin(
|
||||||
'EpProducts',
|
'EpProducts',
|
||||||
'product_detail',
|
'product_detail',
|
||||||
|
|||||||
Reference in new issue
Block a user