Skip to content

Commit 405ce87

Browse files
authored
* Add possibility to save exceptions in file (#81)
* * Add possibility to save exceptions in file
1 parent 0938f7f commit 405ce87

17 files changed

+220
-15
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Version 5.4.0
2+
* Add possibility to save exceptions in file
3+
14
# Version 5.3.1
25
* Fix interface naming
36

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,20 @@ framework:
146146
CodeRhapsodie\DataflowBundle\MessengerMode\JobMessage: async
147147
```
148148

149+
### Exceptions mode
150+
Dataflow can save exceptions in any filesystem you want.
151+
This allows dataflow to save exceptions in filesystem instead of the database
152+
You have to install `league/flysystem`.
153+
154+
To enable exceptions mode:
155+
156+
```yaml
157+
code_rhapsodie_dataflow:
158+
exceptions_mode:
159+
type: 'file'
160+
flysystem_service: 'app.filesystem' #The name of the \League\Flysystem\Filesystem service
161+
```
162+
149163
## Define a dataflow type
150164

151165
This bundle uses a fixed and simple workflow structure in order to let you focus on the data processing logic part of

Tests/Processor/JobProcessorTest.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use CodeRhapsodie\DataflowBundle\Entity\Job;
88
use CodeRhapsodie\DataflowBundle\Event\Events;
99
use CodeRhapsodie\DataflowBundle\Event\ProcessingEvent;
10+
use CodeRhapsodie\DataflowBundle\Gateway\JobGateway;
1011
use CodeRhapsodie\DataflowBundle\Processor\JobProcessor;
1112
use CodeRhapsodie\DataflowBundle\Registry\DataflowTypeRegistryInterface;
1213
use CodeRhapsodie\DataflowBundle\Repository\JobRepository;
@@ -20,14 +21,16 @@ class JobProcessorTest extends TestCase
2021
private JobRepository|MockObject $repository;
2122
private DataflowTypeRegistryInterface|MockObject $registry;
2223
private EventDispatcherInterface|MockObject $dispatcher;
24+
private JobGateway|MockObject $jobGateway;
2325

2426
protected function setUp(): void
2527
{
2628
$this->repository = $this->createMock(JobRepository::class);
2729
$this->registry = $this->createMock(DataflowTypeRegistryInterface::class);
2830
$this->dispatcher = $this->createMock(EventDispatcherInterface::class);
31+
$this->jobGateway = $this->createMock(JobGateway::class);
2932

30-
$this->processor = new JobProcessor($this->repository, $this->registry, $this->dispatcher);
33+
$this->processor = new JobProcessor($this->repository, $this->registry, $this->dispatcher, $this->jobGateway);
3134
}
3235

3336
public function testProcess()
@@ -72,7 +75,7 @@ public function testProcess()
7275
->willReturn($result)
7376
;
7477

75-
$this->repository
78+
$this->jobGateway
7679
->expects($this->exactly(2))
7780
->method('save')
7881
;

src/Command/JobShowCommand.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use CodeRhapsodie\DataflowBundle\Entity\Job;
88
use CodeRhapsodie\DataflowBundle\Factory\ConnectionFactory;
9-
use CodeRhapsodie\DataflowBundle\Repository\JobRepository;
9+
use CodeRhapsodie\DataflowBundle\Gateway\JobGateway;
1010
use Symfony\Component\Console\Attribute\AsCommand;
1111
use Symfony\Component\Console\Command\Command;
1212
use Symfony\Component\Console\Input\InputInterface;
@@ -26,7 +26,7 @@ class JobShowCommand extends Command
2626
Job::STATUS_COMPLETED => 'Completed',
2727
];
2828

29-
public function __construct(private JobRepository $jobRepository, private ConnectionFactory $connectionFactory)
29+
public function __construct(private JobGateway $jobGateway, private ConnectionFactory $connectionFactory)
3030
{
3131
parent::__construct();
3232
}
@@ -58,9 +58,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5858
}
5959

6060
if ($scheduleId) {
61-
$job = $this->jobRepository->findLastForDataflowId($scheduleId);
61+
$job = $this->jobGateway->findLastForDataflowId($scheduleId);
6262
} elseif ($jobId) {
63-
$job = $this->jobRepository->find($jobId);
63+
$job = $this->jobGateway->find($jobId);
6464
} else {
6565
$io->error('You must pass `job-id` or `schedule-id` option.');
6666

src/DependencyInjection/CodeRhapsodieDataflowExtension.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
class CodeRhapsodieDataflowExtension extends Extension
1717
{
18-
public function load(array $configs, ContainerBuilder $container)
18+
public function load(array $configs, ContainerBuilder $container): void
1919
{
2020
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
2121
$loader->load('services.yaml');
@@ -29,6 +29,12 @@ public function load(array $configs, ContainerBuilder $container)
2929

3030
$container->setParameter('coderhapsodie.dataflow.dbal_default_connection', $config['dbal_default_connection']);
3131
$container->setParameter('coderhapsodie.dataflow.default_logger', $config['default_logger']);
32+
$container->setParameter('coderhapsodie.dataflow.exceptions_mode.type', $config['exceptions_mode']['type']);
33+
34+
if ($config['exceptions_mode']['type'] === 'file') {
35+
$container->setParameter('coderhapsodie.dataflow.flysystem_service', $config['exceptions_mode']['flysystem_service']);
36+
$loader->load('exceptions_services.yaml');
37+
}
3238

3339
if ($config['messenger_mode']['enabled']) {
3440
$container->setParameter('coderhapsodie.dataflow.bus', $config['messenger_mode']['bus']);

src/DependencyInjection/Compiler/BusCompilerPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
class BusCompilerPass implements CompilerPassInterface
1414
{
15-
public function process(ContainerBuilder $container)
15+
public function process(ContainerBuilder $container): void
1616
{
1717
if (!$container->hasParameter('coderhapsodie.dataflow.bus')) {
1818
return;

src/DependencyInjection/Compiler/DataflowTypeCompilerPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717
class DataflowTypeCompilerPass implements CompilerPassInterface
1818
{
19-
public function process(ContainerBuilder $container)
19+
public function process(ContainerBuilder $container): void
2020
{
2121
if (!$container->has(DataflowTypeRegistry::class)) {
2222
return;

src/DependencyInjection/Compiler/DefaultLoggerCompilerPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
class DefaultLoggerCompilerPass implements CompilerPassInterface
1414
{
15-
public function process(ContainerBuilder $container)
15+
public function process(ContainerBuilder $container): void
1616
{
1717
$defaultLogger = $container->getParameter('coderhapsodie.dataflow.default_logger');
1818
if (!$container->has($defaultLogger)) {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CodeRhapsodie\DataflowBundle\DependencyInjection\Compiler;
6+
7+
use CodeRhapsodie\DataflowBundle\ExceptionsHandler\FilesystemExceptionHandler;
8+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
9+
use Symfony\Component\DependencyInjection\ContainerBuilder;
10+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
11+
use Symfony\Component\DependencyInjection\Reference;
12+
13+
class ExceptionCompilerPass implements CompilerPassInterface
14+
{
15+
public function process(ContainerBuilder $container): void
16+
{
17+
if (!$container->hasParameter('coderhapsodie.dataflow.flysystem_service')) {
18+
return;
19+
}
20+
21+
$flysystem = $container->getParameter('coderhapsodie.dataflow.flysystem_service');
22+
if (!$container->has($flysystem)) {
23+
throw new InvalidArgumentException(\sprintf('Service "%s" not found', $flysystem));
24+
}
25+
26+
$definition = $container->findDefinition(FilesystemExceptionHandler::class);
27+
$definition->setArgument('$filesystem', new Reference($flysystem));
28+
}
29+
}

src/DependencyInjection/Configuration.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ public function getConfigTreeBuilder(): TreeBuilder
3838
->thenInvalid('You need "symfony/messenger" in order to use Dataflow messenger mode.')
3939
->end()
4040
->end()
41+
->arrayNode('exceptions_mode')
42+
->addDefaultsIfNotSet()
43+
->children()
44+
->scalarNode('type')
45+
->defaultValue('database')
46+
->end()
47+
->scalarNode('flysystem_service')
48+
->end()
49+
->validate()
50+
->ifTrue(static fn ($v): bool => $v['type'] === 'file' && !interface_exists('\League\Flysystem\Filesystem'))
51+
->thenInvalid('You need "league/flysystem" to use Dataflow file exception mode.')
52+
->end()
53+
->end()
54+
->end()
4155
->end()
4256
;
4357

0 commit comments

Comments
 (0)