Skip to content

Commit

Permalink
Remove jobs no longer referenced in the codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
fredden committed May 23, 2024
1 parent c893121 commit 9ebddc6
Show file tree
Hide file tree
Showing 5 changed files with 249 additions and 3 deletions.
89 changes: 89 additions & 0 deletions app/code/Magento/Cron/Cron/CleanOldJobs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

declare(strict_types=1);

namespace Magento\Cron\Cron;

use Magento\Config\App\Config\Type\System;
use Magento\Cron\Model\DeadlockRetrierInterface;
use Magento\Cron\Model\ResourceModel\Schedule;
use Magento\Cron\Model\ScheduleFactory;
use Magento\Cron\Observer\ProcessCronQueueObserver;
use Magento\Framework\App\Config;
use Magento\Framework\Stdlib\DateTime\DateTime;

class CleanOldJobs
{
/**
* This docblock provides no new information
*
* @param Config $config
* @param DateTime $dateTime
* @param DeadlockRetrierInterface $retrier
* @param ScheduleFactory $scheduleFactory
*/
public function __construct(
private readonly Config $config,
private readonly DateTime $dateTime,
private readonly DeadlockRetrierInterface $retrier,
private readonly ScheduleFactory $scheduleFactory,
) {
}

/**
* Run the 'clean_cron_schedule' cronjob
*
* @return void
*/
public function execute(): void
{
$fullConfig = $this->config->get(System::CONFIG_TYPE);
$maxLifetime = 0;

array_walk_recursive(
$fullConfig,
static function ($value, $key) use (&$maxLifetime) {
if ($key === ProcessCronQueueObserver::XML_PATH_HISTORY_SUCCESS
|| $key === ProcessCronQueueObserver::XML_PATH_HISTORY_FAILURE
) {
$maxLifetime = max($maxLifetime, (int) $value);
}
}
);

if ($maxLifetime === 0) {
// Something has gone wrong. Why are there no configuration values?
// Drop out now to avoid doing any damage to this already-broken installation.
return;
}

// The value stored in XML is in minutes, we want seconds.
$maxLifetime *= 60;

// Add one day to avoid removing items which are near their natural expiry anyway.
$maxLifetime += 86400;

/** @var Schedule $scheduleResource */
$scheduleResource = $this->scheduleFactory->create()->getResource();

$currentTime = $this->dateTime->gmtTimestamp();
$deleteBefore = $scheduleResource->getConnection()->formatDate($currentTime - $maxLifetime);

$this->retrier->execute(
function () use ($scheduleResource, $deleteBefore) {
$scheduleResource->getConnection()->delete(
$scheduleResource->getTable('cron_schedule'),
[
'scheduled_at < ?' => $deleteBefore,
]
);
},
$scheduleResource->getConnection()
);
}
}
141 changes: 141 additions & 0 deletions app/code/Magento/Cron/Test/Unit/Cron/CleanOldJobsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

declare(strict_types=1);

namespace Magento\Cron\Test\Unit\Cron;

use Magento\Cron\Cron\CleanOldJobs;
use Magento\Cron\Model\DeadlockRetrierInterface;
use Magento\Cron\Model\ResourceModel\Schedule as ScheduleResourceModel;
use Magento\Cron\Model\Schedule;
use Magento\Cron\Model\ScheduleFactory;
use Magento\Framework\App\Config;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\Stdlib\DateTime\DateTime;
use PHPUnit\Framework\TestCase;

// phpcs:disable Magento2.Commenting.ClassPropertyPHPDocFormatting.Missing, because such comments would add no value.

class CleanOldJobsTest extends TestCase
{
private CleanOldJobs $cleanOldJobs;
private Config $configMock;
private ScheduleFactory $scheduleFactoryMock;
private DateTime $dateTimeMock;
private ScheduleResourceModel $scheduleResourceMock;
private DeadlockRetrierInterface $retrierMock;
private Schedule $scheduleMock;
private int $time = 1501538400;

/**
* @inheritdoc
*/
protected function setUp(): void
{
$this->configMock = $this->getMockBuilder(Config::class)
->disableOriginalConstructor()
->getMock();

$this->dateTimeMock = $this->getMockBuilder(DateTime::class)
->disableOriginalConstructor()
->getMock();
$this->dateTimeMock->method('gmtTimestamp')
->willReturn($this->time);

$this->retrierMock = $this->getMockForAbstractClass(DeadlockRetrierInterface::class);

$this->scheduleFactoryMock = $this->getMockBuilder(ScheduleFactory::class)
->onlyMethods(['create'])
->disableOriginalConstructor()
->getMock();

$this->scheduleMock = $this->getMockBuilder(Schedule::class)
->disableOriginalConstructor()
->getMock();

$this->scheduleResourceMock = $this->getMockBuilder(ScheduleResourceModel::class)
->disableOriginalConstructor()
->getMock();

$this->scheduleMock
->method('getResource')
->willReturn($this->scheduleResourceMock);

$this->scheduleFactoryMock
->method('create')
->willReturn($this->scheduleMock);

$this->cleanOldJobs = new CleanOldJobs(
$this->configMock,
$this->dateTimeMock,
$this->retrierMock,
$this->scheduleFactoryMock
);
}

public function testSuccess(): void
{
$tableName = 'cron_schedule';

$this->configMock->expects($this->once())
->method('get')
->with('system')
->willReturn([
'history_success_lifetime' => 100,
'history_failure_lifetime' => 200,
]);

$connectionMock = $this->getMockForAbstractClass(AdapterInterface::class);

$connectionMock->expects($this->once())
->method('delete')
->with($tableName, [
'scheduled_at < ?' => '$this->time - (86400 + (200 * 60))',
]);

$connectionMock->method('formatDate')
->willReturnMap([
[1501538400, true, '$this->time'],
[1501538200, true, '$this->time - 200'],
[1501526400, true, '$this->time - (200 * 60)'],
[1501452000, true, '$this->time - 86400'],
[1501451800, true, '$this->time - (86400 + 200)'],
[1501440000, true, '$this->time - (86400 + (200 * 60))'],
]);

$this->scheduleResourceMock->expects($this->once())
->method('getTable')
->with($tableName)
->willReturn($tableName);
$this->scheduleResourceMock->expects($this->exactly(3))
->method('getConnection')
->willReturn($connectionMock);

$this->retrierMock->expects($this->once())
->method('execute')
->willReturnCallback(
function ($callback) {
return $callback();
}
);

$this->cleanOldJobs->execute();
}

public function testNoActionWhenEmptyConfig(): void
{
$this->configMock->expects($this->once())
->method('get')
->with('system')
->willReturn([]);

$this->scheduleFactoryMock->expects($this->never())->method('create');

$this->cleanOldJobs->execute();
}
}
4 changes: 1 addition & 3 deletions app/code/Magento/Cron/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@
"require": {
"php": "~8.1.0||~8.2.0||~8.3.0",
"magento/framework": "*",
"magento/module-config": "^100.1.2 || ^101.0",
"magento/module-store": "*"
},
"suggest": {
"magento/module-config": "*"
},
"type": "magento2-module",
"license": [
"OSL-3.0",
Expand Down
17 changes: 17 additions & 0 deletions app/code/Magento/Cron/etc/crontab.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
<group id="default">
<job name="clean_cron_schedule"
instance="Magento\Cron\Cron\CleanOldJobs"
method="execute">
<schedule>0 0 * * *</schedule>
</job>
</group>
</config>
1 change: 1 addition & 0 deletions app/code/Magento/Cron/etc/module.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Magento_Cron" >
<sequence>
<module name="Magento_Config"/>
<module name="Magento_Store"/>
</sequence>
</module>
Expand Down

0 comments on commit 9ebddc6

Please sign in to comment.