Skip to content

Commit c2133c6

Browse files
jeremycrjbcr
andauthored
Added cleanup commands (#84)
* Added cleanup commands * php-cs-fixer * Apply suggestions from code review Co-authored-by: jbcr <51637606+jbcr@users.noreply.github.com> * Updated for PHP 8.2 * PHPStan --------- Co-authored-by: jbcr <51637606+jbcr@users.noreply.github.com>
1 parent 6ebbdbd commit c2133c6

38 files changed

Lines changed: 332 additions & 248 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Version 5.5.0
2+
* Added cleanup commands
3+
* Updated for PHP 8.2
4+
15
# Version 5.4.1
26
* Fix File Exceptions integration
37

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ providing an easy way to create import / export dataflow.
55

66
| Dataflow | Symfony | Support |
77
|----------|--------------------------|---------|
8-
| 5.x | 7.x | yes |
8+
| 5.x | ^7.3 | yes |
99
| 4.x | 3.4 \| 4.x \| 5.x \| 6.x | yes |
1010
| 3.x | 3.4 \| 4.x \| 5.x | no |
1111
| 2.x | 3.4 \| 4.x | no |
@@ -243,7 +243,6 @@ implementing `DataflowTypeInterface`.
243243

244244
Otherwise, manually add the tag `coderhapsodie.dataflow.type` in your dataflow type service configuration:
245245

246-
```yaml
247246
```yaml
248247
CodeRhapsodie\DataflowExemple\DataflowType\MyFirstDataflowType:
249248
tags:
@@ -598,6 +597,10 @@ the messenger component instead.
598597

599598
`code-rhapsodie:dataflow:dump-schema` Generates schema create / update SQL queries
600599

600+
`code-rhapsodie:dataflow:job:set-crashed` Jobs that have been in the "running" status for too long will be set in the "crashed" status.
601+
602+
`code-rhapsodie:dataflow:job:cleanup` Remove old completed or crashed jobs
603+
601604
### Work with many databases
602605

603606
All commands have a `--connection` option to define what Doctrine DBAL connection to use during execution.

Tests/DataflowType/AbstractDataflowTypeTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public function testProcess()
1818

1919
$dataflowType = new class($label, $options, $values, $testCase) extends AbstractDataflowType
2020
{
21-
public function __construct(private string $label, private array $options, private array $values, private TestCase $testCase)
21+
public function __construct(private readonly string $label, private readonly array $options, private readonly array $values, private readonly TestCase $testCase)
2222
{
2323
}
2424

composer.json

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,33 +41,35 @@
4141
}
4242
},
4343
"require": {
44-
"php": "^8.0",
44+
"php": "^8.2",
4545
"ext-json": "*",
4646
"doctrine/dbal": "^3.0||^4.0",
4747
"doctrine/doctrine-bundle": "^2.0",
4848
"monolog/monolog": "^2.0||^3.0",
4949
"psr/log": "^1.1||^2.0||^3.0",
50-
"symfony/config": "^7.0",
51-
"symfony/console": "^7.0",
52-
"symfony/dependency-injection": "^7.0",
53-
"symfony/event-dispatcher": "^7.0",
54-
"symfony/http-kernel": "^7.0",
55-
"symfony/lock": "^7.0",
56-
"symfony/monolog-bridge": "^7.0",
57-
"symfony/options-resolver": "^7.0",
58-
"symfony/validator": "^7.0",
59-
"symfony/yaml": "^7.0"
50+
"symfony/config": "^7.3",
51+
"symfony/console": "^7.3",
52+
"symfony/dependency-injection": "^7.3",
53+
"symfony/event-dispatcher": "^7.3",
54+
"symfony/http-kernel": "^7.3",
55+
"symfony/lock": "^7.3",
56+
"symfony/monolog-bridge": "^7.3",
57+
"symfony/options-resolver": "^7.3",
58+
"symfony/validator": "^7.3",
59+
"symfony/yaml": "^7.3"
6060
},
6161
"require-dev": {
6262
"amphp/amp": "^2.5",
63+
"ekino/phpstan-banned-code": "^3.2",
6364
"friendsofphp/php-cs-fixer": "^3.75",
6465
"phpunit/phpunit": "^11",
6566
"portphp/portphp": "^1.9",
6667
"rector/rector": "^2.0",
67-
"symfony/messenger": "^7.0"
68+
"symfony/messenger": "^7.3"
6869
},
6970
"suggest": {
7071
"amphp/amp": "Provide asynchronous steps for your dataflows",
72+
"league/flysystem": "Allows Dataflow file exception mode, i.e. saving job exceptions outside the database",
7173
"portphp/portphp": "Provides generic readers, steps and writers for your dataflows.",
7274
"symfony/messenger": "Allows messenger mode, i.e. letting workers run jobs"
7375
},

phpstan.neon.dist

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
includes:
2+
- vendor/ekino/phpstan-banned-code/extension.neon
3+
parameters:
4+
level: 5
5+
paths:
6+
- src/

rector.php

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,20 @@
22

33
declare(strict_types=1);
44

5-
use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
65
use Rector\Config\RectorConfig;
76
use Rector\Set\ValueObject\LevelSetList;
87
use Rector\Symfony\Set\SymfonySetList;
98

10-
return static function (RectorConfig $rectorConfig): void {
11-
$rectorConfig->paths([
12-
__DIR__ . '/src',
13-
__DIR__ . '/Tests',
14-
]);
15-
16-
// register a single rule
17-
$rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
18-
19-
$rectorConfig->sets([
20-
SymfonySetList::SYMFONY_70,
9+
return RectorConfig::configure()
10+
->withPaths([
11+
__DIR__.'/src',
12+
__DIR__.'/Tests',
13+
])
14+
->withComposerBased(doctrine: true, symfony: true)
15+
->withSets([
2116
SymfonySetList::SYMFONY_CODE_QUALITY,
2217
SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION,
23-
LevelSetList::UP_TO_PHP_80,
24-
]);
25-
};
18+
SymfonySetList::SYMFONY_73,
19+
LevelSetList::UP_TO_PHP_82,
20+
])
21+
;

src/Command/AddScheduledDataflowCommand.php

Lines changed: 18 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,46 +9,34 @@
99
use CodeRhapsodie\DataflowBundle\Registry\DataflowTypeRegistryInterface;
1010
use CodeRhapsodie\DataflowBundle\Repository\ScheduledDataflowRepository;
1111
use Symfony\Component\Console\Attribute\AsCommand;
12-
use Symfony\Component\Console\Command\Command;
13-
use Symfony\Component\Console\Input\InputInterface;
14-
use Symfony\Component\Console\Input\InputOption;
15-
use Symfony\Component\Console\Output\OutputInterface;
12+
use Symfony\Component\Console\Attribute\Option;
1613
use Symfony\Component\Console\Style\SymfonyStyle;
1714
use Symfony\Component\Validator\Validator\ValidatorInterface;
1815

1916
/**
2017
* @codeCoverageIgnore
2118
*/
22-
#[AsCommand('code-rhapsodie:dataflow:schedule:add', 'Create a scheduled dataflow')]
23-
class AddScheduledDataflowCommand extends Command
19+
#[AsCommand('code-rhapsodie:dataflow:schedule:add', 'Create a scheduled dataflow', help: <<<'TXT'
20+
The <info>%command.name%</info> allows you to create a new scheduled dataflow.
21+
TXT)]
22+
final readonly class AddScheduledDataflowCommand
2423
{
2524
public function __construct(private DataflowTypeRegistryInterface $registry, private ScheduledDataflowRepository $scheduledDataflowRepository, private ValidatorInterface $validator, private ConnectionFactory $connectionFactory)
2625
{
27-
parent::__construct();
2826
}
2927

30-
protected function configure(): void
31-
{
32-
$this
33-
->setHelp('The <info>%command.name%</info> allows you to create a new scheduled dataflow.')
34-
->addOption('label', null, InputOption::VALUE_REQUIRED, 'Label of the scheduled dataflow')
35-
->addOption('type', null, InputOption::VALUE_REQUIRED, 'Type of the scheduled dataflow (FQCN)')
36-
->addOption(
37-
'options',
38-
null,
39-
InputOption::VALUE_OPTIONAL,
40-
'Options of the scheduled dataflow (ex: {"option1": "value1", "option2": "value2"})'
41-
)
42-
->addOption('frequency', null, InputOption::VALUE_REQUIRED, 'Frequency of the scheduled dataflow')
43-
->addOption('first_run', null, InputOption::VALUE_REQUIRED, 'Date for the first run of the scheduled dataflow (Y-m-d H:i:s)')
44-
->addOption('enabled', null, InputOption::VALUE_REQUIRED, 'State of the scheduled dataflow')
45-
->addOption('connection', null, InputOption::VALUE_REQUIRED, 'Define the DBAL connection to use');
46-
}
47-
48-
protected function execute(InputInterface $input, OutputInterface $output): int
49-
{
50-
if ($input->getOption('connection') !== null) {
51-
$this->connectionFactory->setConnectionName($input->getOption('connection'));
28+
public function __invoke(
29+
SymfonyStyle $io,
30+
#[Option('Label of the scheduled dataflow')] ?string $label = null,
31+
#[Option('Type of the scheduled dataflow (FQCN)')] ?string $type = null,
32+
#[Option('Options of the scheduled dataflow (ex: {"option1": "value1", "option2": "value2"})')] ?string $options = null,
33+
#[Option('Frequency of the scheduled dataflow')] ?string $frequency = null,
34+
#[Option('Date for the first run of the scheduled dataflow (Y-m-d H:i:s)')] ?string $firstRun = null,
35+
#[Option('State of the scheduled dataflow')] ?bool $enabled = null,
36+
#[Option('Define the DBAL connection to use')] ?string $connection = null,
37+
): int {
38+
if ($connection !== null) {
39+
$this->connectionFactory->setConnectionName($connection);
5240
}
5341
$choices = [];
5442
$typeMapping = [];
@@ -57,36 +45,29 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5745
$typeMapping[$dataflowType->getLabel()] = $fqcn;
5846
}
5947

60-
$io = new SymfonyStyle($input, $output);
61-
$label = $input->getOption('label');
6248
if (!$label) {
6349
$label = $io->ask('What is the scheduled dataflow label?');
6450
}
65-
$type = $input->getOption('type');
6651
if (!$type) {
6752
$selectedType = $io->choice('What is the scheduled dataflow type?', $choices);
6853
$type = $typeMapping[$selectedType];
6954
}
70-
$options = $input->getOption('options');
7155
if (!$options) {
7256
$options = $io->ask(
7357
'What are the launch options for the scheduled dataflow? (ex: {"option1": "value1", "option2": "value2"})',
7458
json_encode([])
7559
);
7660
}
77-
$frequency = $input->getOption('frequency');
7861
if (!$frequency) {
7962
$frequency = $io->choice(
8063
'What is the frequency for the scheduled dataflow?',
8164
ScheduledDataflow::AVAILABLE_FREQUENCIES
8265
);
8366
}
84-
$firstRun = $input->getOption('first_run');
8567
if (!$firstRun) {
8668
$firstRun = $io->ask('When is the first execution of the scheduled dataflow (format: Y-m-d H:i:s)?');
8769
}
88-
$enabled = $input->getOption('enabled');
89-
if (!$enabled) {
70+
if ($enabled === null) {
9071
$enabled = $io->confirm('Enable the scheduled dataflow?');
9172
}
9273

src/Command/ChangeScheduleStatusCommand.php

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,63 +7,58 @@
77
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
88
use CodeRhapsodie\DataflowBundle\Factory\ConnectionFactory;
99
use CodeRhapsodie\DataflowBundle\Repository\ScheduledDataflowRepository;
10+
use Symfony\Component\Console\Attribute\Argument;
1011
use Symfony\Component\Console\Attribute\AsCommand;
11-
use Symfony\Component\Console\Command\Command;
12-
use Symfony\Component\Console\Input\InputArgument;
13-
use Symfony\Component\Console\Input\InputInterface;
14-
use Symfony\Component\Console\Input\InputOption;
15-
use Symfony\Component\Console\Output\OutputInterface;
12+
use Symfony\Component\Console\Attribute\Option;
1613
use Symfony\Component\Console\Style\SymfonyStyle;
1714

1815
/**
1916
* @codeCoverageIgnore
2017
*/
21-
#[AsCommand('code-rhapsodie:dataflow:schedule:change-status', 'Change schedule status')]
22-
class ChangeScheduleStatusCommand extends Command
18+
#[AsCommand('code-rhapsodie:dataflow:schedule:change-status', 'Change schedule status', help: <<<'TXT'
19+
The <info>%command.name%</info> command able you to change schedule status.
20+
TXT)]
21+
final readonly class ChangeScheduleStatusCommand
2322
{
2423
public function __construct(private ScheduledDataflowRepository $scheduledDataflowRepository, private ConnectionFactory $connectionFactory)
2524
{
26-
parent::__construct();
2725
}
2826

29-
protected function configure(): void
30-
{
31-
$this
32-
->setHelp('The <info>%command.name%</info> command able you to change schedule status.')
33-
->addArgument('schedule-id', InputArgument::REQUIRED, 'Id of the schedule')
34-
->addOption('enable', null, InputOption::VALUE_NONE, 'Enable the schedule')
35-
->addOption('disable', null, InputOption::VALUE_NONE, 'Disable the schedule')
36-
->addOption('connection', null, InputOption::VALUE_REQUIRED, 'Define the DBAL connection to use');
37-
}
38-
39-
protected function execute(InputInterface $input, OutputInterface $output): int
40-
{
41-
if ($input->getOption('connection') !== null) {
42-
$this->connectionFactory->setConnectionName($input->getOption('connection'));
27+
public function __invoke(
28+
SymfonyStyle $io,
29+
#[Argument('Id of the schedule')] int $scheduleId,
30+
#[Option('Enable the schedule')] ?bool $enable = null,
31+
#[Option('Disable the schedule')] ?bool $disable = null,
32+
#[Option('Define the DBAL connection to use')] ?string $connection = null,
33+
): int {
34+
if ($connection !== null) {
35+
$this->connectionFactory->setConnectionName($connection);
4336
}
44-
$io = new SymfonyStyle($input, $output);
37+
4538
/** @var ScheduledDataflow|null $schedule */
46-
$schedule = $this->scheduledDataflowRepository->find((int) $input->getArgument('schedule-id'));
39+
$schedule = $this->scheduledDataflowRepository->find($scheduleId);
4740

4841
if (!$schedule) {
49-
$io->error(\sprintf('Cannot find scheduled dataflow with id "%d".', $input->getArgument('schedule-id')));
42+
$io->error(\sprintf('Cannot find scheduled dataflow with id "%d".', $scheduleId));
5043

5144
return 1;
5245
}
5346

54-
if ($input->getOption('enable') && $input->getOption('disable')) {
47+
if ($enable !== null && $disable !== null) {
5548
$io->error('You cannot pass enable and disable options in the same time.');
5649

5750
return 2;
5851
}
59-
if (!$input->getOption('enable') && !$input->getOption('disable')) {
52+
if ($enable === null && $disable === null) {
6053
$io->error('You must pass enable or disable option.');
6154

6255
return 3;
6356
}
6457

58+
$enable = $enable ?? !$disable;
59+
6560
try {
66-
$schedule->setEnabled($input->getOption('enable'));
61+
$schedule->setEnabled($enable);
6762
$this->scheduledDataflowRepository->save($schedule);
6863
$io->success(\sprintf('Schedule with id "%s" has been successfully updated.', $schedule->getId()));
6964
} catch (\Exception $e) {

0 commit comments

Comments
 (0)