Skip to content

Commit ee5703f

Browse files
committed
Added cleanup commands
1 parent 6ebbdbd commit ee5703f

9 files changed

Lines changed: 128 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Version 5.5.0
2+
* Added cleanup commands
3+
14
# Version 5.4.1
25
* Fix File Exceptions integration
36

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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: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.

src/Command/JobCleanupCommand.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CodeRhapsodie\DataflowBundle\Command;
6+
7+
use CodeRhapsodie\DataflowBundle\Repository\JobRepository;
8+
use Symfony\Component\Console\Attribute\AsCommand;
9+
use Symfony\Component\Console\Command\Command;
10+
use Symfony\Component\Console\Input\InputInterface;
11+
use Symfony\Component\Console\Output\OutputInterface;
12+
13+
#[AsCommand(name: 'code-rhapsodie:job_cleanup', description: 'Cleanup job history.')]
14+
class JobCleanupCommand extends Command
15+
{
16+
public function __construct(private JobRepository $jobRepository, private int $retention)
17+
{
18+
parent::__construct();
19+
}
20+
21+
protected function configure()
22+
{
23+
$this->setHelp('Job retention can be configured with the "job_history.retention" configuration.');
24+
}
25+
26+
protected function execute(InputInterface $input, OutputInterface $output): int
27+
{
28+
$this->jobRepository->deleteOld($this->retention);
29+
30+
return Command::SUCCESS;
31+
}
32+
}

src/Command/SetCrashedCommand.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CodeRhapsodie\DataflowBundle\Command;
6+
7+
use CodeRhapsodie\DataflowBundle\Repository\JobRepository;
8+
use Symfony\Component\Console\Attribute\AsCommand;
9+
use Symfony\Component\Console\Command\Command;
10+
use Symfony\Component\Console\Input\InputInterface;
11+
use Symfony\Component\Console\Output\OutputInterface;
12+
13+
#[AsCommand(name: 'code-rhapsodie:set_crashed', description: 'Set long running jobs as crashed.')]
14+
class SetCrashedCommand extends Command
15+
{
16+
public function __construct(private JobRepository $jobRepository, private int $crashedDelay)
17+
{
18+
parent::__construct();
19+
}
20+
21+
protected function configure()
22+
{
23+
$this->setHelp('How long jobs have to run before they are set as crashed can be configured with the "job_history.crashed_delay" configuration.');
24+
}
25+
26+
protected function execute(InputInterface $input, OutputInterface $output): int
27+
{
28+
$this->jobRepository->crashLongRunning($this->crashedDelay);
29+
30+
return Command::SUCCESS;
31+
}
32+
}

src/DependencyInjection/CodeRhapsodieDataflowExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public function load(array $configs, ContainerBuilder $container): void
3030
$container->setParameter('coderhapsodie.dataflow.dbal_default_connection', $config['dbal_default_connection']);
3131
$container->setParameter('coderhapsodie.dataflow.default_logger', $config['default_logger']);
3232
$container->setParameter('coderhapsodie.dataflow.exceptions_mode.type', $config['exceptions_mode']['type']);
33+
$container->setParameter('coderhapsodie.dataflow.job_history.retention', $config['job_history']['retention']);
34+
$container->setParameter('coderhapsodie.dataflow.job_history.crashed_delay', $config['job_history']['crashed_delay']);
3335

3436
if ($config['exceptions_mode']['type'] === 'file') {
3537
$container->setParameter('coderhapsodie.dataflow.flysystem_service', $config['exceptions_mode']['flysystem_service']);

src/DependencyInjection/Configuration.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,20 @@ public function getConfigTreeBuilder(): TreeBuilder
5252
->thenInvalid('You need "league/flysystem" to use Dataflow file exception mode.')
5353
->end()
5454
->end()
55+
->arrayNode('job_history')
56+
->addDefaultsIfNotSet()
57+
->children()
58+
->integerNode('retention')
59+
->defaultValue(30)
60+
->min(0)
61+
->info('How many days completed and crashed jobs are kept when running the cleanup command.')
62+
->end()
63+
->integerNode('crashed_delay')
64+
->defaultValue(24)
65+
->min(24)
66+
->info('Jobs running for more than this many hours will be set as crashed when running the cleanup command.')
67+
->end()
68+
->end()
5569
->end()
5670
;
5771

src/Entity/Job.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Job
1717
public const STATUS_RUNNING = 1;
1818
public const STATUS_COMPLETED = 2;
1919
public const STATUS_QUEUED = 3;
20+
public const STATUS_CRASHED = 4;
2021

2122
private const KEYS = [
2223
'id',

src/Repository/JobRepository.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,33 @@ public function createQueryBuilder($alias = null): QueryBuilder
151151
return $qb;
152152
}
153153

154+
public function crashLongRunning(int $hours): void
155+
{
156+
$qb = $this->connection->createQueryBuilder();
157+
$qb->update(static::TABLE_NAME, 'j')
158+
->set('j.status', ':new_status')
159+
->set('j.end_time', ':now')
160+
->andWhere('j.status = :status')
161+
->andWhere('j.start_time < :date')
162+
->setParameter('status', Job::STATUS_RUNNING)
163+
->setParameter('date', new \DateTime("- {$hours} hours"), 'datetime')
164+
->setParameter('new_status', Job::STATUS_CRASHED)
165+
->setParameter('now', new \DateTime(), 'datetime')
166+
->executeStatement()
167+
;
168+
}
169+
170+
public function deleteOld(int $days): void
171+
{
172+
$qb = $this->connection->createQueryBuilder();
173+
$qb->delete(static::TABLE_NAME, 'j')
174+
->andWhere($qb->expr()->in('j.status', [Job::STATUS_COMPLETED, Job::STATUS_CRASHED]))
175+
->andWhere('j.end_time < :date')
176+
->setParameter('date', new \DateTime("- {$days} days"), 'datetime')
177+
->executeStatement()
178+
;
179+
}
180+
154181
private function returnFirstOrNull(QueryBuilder $qb): ?Job
155182
{
156183
$stmt = $qb->executeQuery();

src/Resources/config/services.yaml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ services:
33
public: false
44

55
CodeRhapsodie\DataflowBundle\Registry\DataflowTypeRegistryInterface: '@CodeRhapsodie\DataflowBundle\Registry\DataflowTypeRegistry'
6-
CodeRhapsodie\DataflowBundle\Registry\DataflowTypeRegistry:
6+
CodeRhapsodie\DataflowBundle\Registry\DataflowTypeRegistry: ~
77

88
CodeRhapsodie\DataflowBundle\Command\AddScheduledDataflowCommand:
99
arguments:
@@ -100,3 +100,15 @@ services:
100100
arguments:
101101
$repository: '@CodeRhapsodie\DataflowBundle\Repository\JobRepository'
102102
$exceptionHandler: '@CodeRhapsodie\DataflowBundle\ExceptionsHandler\ExceptionHandlerInterface'
103+
104+
CodeRhapsodie\DataflowBundle\Command\JobCleanupCommand:
105+
arguments:
106+
$jobRepository: '@CodeRhapsodie\DataflowBundle\Repository\JobRepository'
107+
$retention: '%coderhapsodie.dataflow.job_history.retention%'
108+
tags: ['console.command']
109+
110+
CodeRhapsodie\DataflowBundle\Command\SetCrashedCommand:
111+
arguments:
112+
$jobRepository: '@CodeRhapsodie\DataflowBundle\Repository\JobRepository'
113+
$crashedDelay: '%coderhapsodie.dataflow.job_history.crashed_delay%'
114+
tags: ['console.command']

0 commit comments

Comments
 (0)