Skip to content

Commit ef91c61

Browse files
committed
Merge branch 'add-exclude-group-to-cron-run-command' into feature-ukraine-regions
2 parents e4e2f71 + 34f9f72 commit ef91c61

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed

app/code/Magento/Cron/Console/Command/CronCommand.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ class CronCommand extends Command
3535
public const INPUT_KEY_GROUP = 'group';
3636

3737
/**
38+
* Name of input option
39+
*/
40+
public const INPUT_KEY_EXCLUDE_GROUP = 'exclude-group';
41+
42+
/**
43+
*
3844
* @var ObjectManagerFactory
3945
*/
4046
private $objectManagerFactory;
@@ -73,6 +79,12 @@ protected function configure()
7379
InputOption::VALUE_REQUIRED,
7480
'Run jobs only from specified group'
7581
),
82+
new InputOption(
83+
self::INPUT_KEY_EXCLUDE_GROUP,
84+
null,
85+
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
86+
'Exclude jobs from the specified group'
87+
),
7688
new InputOption(
7789
Cli::INPUT_KEY_BOOTSTRAP,
7890
null,
@@ -102,13 +114,15 @@ protected function execute(InputInterface $input, OutputInterface $output)
102114
$output->writeln('<info>' . 'Cron is disabled. Jobs were not run.' . '</info>');
103115
return Cli::RETURN_SUCCESS;
104116
}
117+
105118
// phpcs:ignore Magento2.Security.Superglobal
106119
$omParams = $_SERVER;
107120
$omParams[StoreManager::PARAM_RUN_CODE] = 'admin';
108121
$omParams[Store::CUSTOM_ENTRY_POINT_PARAM] = true;
109122
$objectManager = $this->objectManagerFactory->create($omParams);
110123

111124
$params[self::INPUT_KEY_GROUP] = $input->getOption(self::INPUT_KEY_GROUP);
125+
$params[self::INPUT_KEY_EXCLUDE_GROUP] = $input->getOption(self::INPUT_KEY_EXCLUDE_GROUP);
112126
$params[ProcessCronQueueObserver::STANDALONE_PROCESS_STARTED] = '0';
113127
$bootstrap = $input->getOption(Cli::INPUT_KEY_BOOTSTRAP);
114128
if ($bootstrap) {

app/code/Magento/Cron/Observer/ProcessCronQueueObserver.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,9 @@ function ($a, $b) {
257257
if (!$this->isGroupInFilter($groupId)) {
258258
continue;
259259
}
260+
if ($this->isGroupInExcludeFilter($groupId)) {
261+
continue;
262+
}
260263
if ($this->_request->getParam(self::STANDALONE_PROCESS_STARTED) !== '1'
261264
&& $this->getCronGroupConfigurationValue($groupId, 'use_separate_process') == 1
262265
) {
@@ -809,6 +812,18 @@ private function isGroupInFilter($groupId): bool
809812
&& trim($this->_request->getParam('group'), "'") !== $groupId);
810813
}
811814

815+
/**
816+
* Is Group In Exclude Filter.
817+
*
818+
* @param string $groupId
819+
* @return bool
820+
*/
821+
private function isGroupInExcludeFilter($groupId): bool
822+
{
823+
$excludeGroup = $this->_request->getParam('exclude-group', []);
824+
return is_array($excludeGroup) && in_array($groupId, $excludeGroup);
825+
}
826+
812827
/**
813828
* Process pending jobs.
814829
*

dev/tests/integration/testsuite/Magento/Cron/Observer/ProcessCronQueueObserverTest.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\Cron\Observer;
77

8+
use Magento\Cron\Observer\ProcessCronQueueObserver;
89
use \Magento\TestFramework\Helper\Bootstrap;
910

1011
class ProcessCronQueueObserverTest extends \PHPUnit\Framework\TestCase
@@ -49,4 +50,119 @@ public function testDispatchNoFailed()
4950
$this->fail($item->getMessages());
5051
}
5152
}
53+
54+
/**
55+
* @param array $expectedGroupsToRun
56+
* @param null $group
57+
* @param null $excludeGroup
58+
* @dataProvider groupFiltersDataProvider
59+
*/
60+
public function testGroupFilters(array $expectedGroupsToRun, $group = null, $excludeGroup = null)
61+
{
62+
$config = $this->createMock(\Magento\Cron\Model\ConfigInterface::class);
63+
$config->expects($this->any())
64+
->method('getJobs')
65+
->willReturn($this->getFilterTestCronGroups());
66+
67+
$request = Bootstrap::getObjectManager()->get(\Magento\Framework\App\Console\Request::class);
68+
$lockManager = $this->createMock(\Magento\Framework\Lock\LockManagerInterface::class);
69+
70+
// The jobs are locked when they are run, assert on them to see which groups would run
71+
$expectedLockData = [];
72+
foreach ($expectedGroupsToRun as $expectedGroupToRun) {
73+
$expectedLockData[] = [
74+
ProcessCronQueueObserver::LOCK_PREFIX . $expectedGroupToRun,
75+
ProcessCronQueueObserver::LOCK_TIMEOUT
76+
];
77+
}
78+
79+
// No expected lock data, means we should never call it
80+
if (empty($expectedLockData)) {
81+
$lockManager->expects($this->never())
82+
->method('lock');
83+
}
84+
85+
$lockManager->expects($this->exactly(count($expectedLockData)))
86+
->method('lock')
87+
->withConsecutive(...$expectedLockData);
88+
89+
$request->setParams(
90+
[
91+
'group' => $group,
92+
'exclude-group' => $excludeGroup,
93+
'standaloneProcessStarted' => '1'
94+
]
95+
);
96+
$this->_model = Bootstrap::getObjectManager()
97+
->create(\Magento\Cron\Observer\ProcessCronQueueObserver::class, [
98+
'request' => $request,
99+
'lockManager' => $lockManager,
100+
'config' => $config
101+
]);
102+
$this->_model->execute(new \Magento\Framework\Event\Observer());
103+
}
104+
105+
/**
106+
* @return array|array[]
107+
*/
108+
public function groupFiltersDataProvider(): array
109+
{
110+
111+
return [
112+
'no flags runs all groups' => [
113+
['index', 'consumers', 'default'] // groups to run
114+
],
115+
'--group=default should run' => [
116+
['default'], // groups to run
117+
'default', // --group default
118+
],
119+
'--group=default with --exclude-group=default, nothing should run' => [
120+
[], // groups to run
121+
'default', // --group default
122+
['default'], // --exclude-group default
123+
],
124+
'--group=default with --exclude-group=index, default should run' => [
125+
['default'], // groups to run
126+
'default', // --group default
127+
['index'], // --exclude-group index
128+
],
129+
'--group=index with --exclude-group=default, index should run' => [
130+
['index'], // groups to run
131+
'index', // --group index
132+
['default'], // --exclude-group default
133+
],
134+
'--exclude-group=index, all other groups should run' => [
135+
['consumers', 'default'], // groups to run, all but index
136+
null, //
137+
['index'] // --exclude-group index
138+
],
139+
'--exclude-group for every group runs nothing' => [
140+
[], // groups to run, none
141+
null, //
142+
['default', 'consumers', 'index'] // groups to exclude, all of them
143+
],
144+
'exclude all groups but consumers, consumers runs' => [
145+
['consumers'],
146+
null,
147+
['index', 'default']
148+
],
149+
];
150+
}
151+
152+
/**
153+
* Only run the filter group tests with a limited set of cron groups, keeps tests consistent between EE and CE
154+
*
155+
* @return array
156+
*/
157+
private function getFilterTestCronGroups()
158+
{
159+
$listOfGroups = [];
160+
$config = Bootstrap::getObjectManager()->get(\Magento\Cron\Model\ConfigInterface::class);
161+
foreach ($config->getJobs() as $groupId => $data) {
162+
if (in_array($groupId, ['default', 'consumers', 'index'])) {
163+
$listOfGroups[$groupId] = $data;
164+
}
165+
}
166+
return $listOfGroups;
167+
}
52168
}

0 commit comments

Comments
 (0)