Skip to content

Commit 1ce9e3c

Browse files
committed
Dispatch invalid item exception inside item step
1 parent 145289f commit 1ce9e3c

File tree

6 files changed

+311
-83
lines changed

6 files changed

+311
-83
lines changed

Event/InvalidItemEvent.php

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

33
namespace Oro\Bundle\BatchBundle\Event;
44

5-
use Oro\Bundle\NotificationBundle\Entity\Event;
5+
use Symfony\Component\EventDispatcher\Event;
66

77
/**
88
* Invalid Item Event

Item/InvalidItemException.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Oro\Bundle\BatchBundle\Item;
4+
5+
/**
6+
* Exception throw during step execution when an item is invalid
7+
*
8+
* @author Gildas Quemener <[email protected]>
9+
* @copyright 2013 Akeneo SAS (http://www.akeneo.com)
10+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
11+
*/
12+
class InvalidItemException extends \Exception
13+
{
14+
/** @var array */
15+
protected $item;
16+
17+
/**
18+
* Constructor
19+
*
20+
* @param string $message
21+
* @param array $item
22+
*/
23+
public function __construct($message, array $item)
24+
{
25+
parent::__construct($message);
26+
27+
$this->item = $item;
28+
}
29+
30+
/**
31+
* Get the invalid item
32+
*/
33+
public function getItem()
34+
{
35+
return $this->item;
36+
}
37+
}

Item/InvalidItemExceptionTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Oro\Bundle\BatchBundle\Item;
4+
5+
/**
6+
* Test related class
7+
*
8+
* @author Gildas Quemener <[email protected]>
9+
* @copyright 2013 Akeneo SAS (http://www.akeneo.com)
10+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
11+
*/
12+
class InvalidItemExceptionTest extends \PHPUnit_Framework_TestCase
13+
{
14+
protected function setUp()
15+
{
16+
$this->exception = new InvalidItemException(
17+
'Tango is down, I repeat...',
18+
array('foo' => 'fighter')
19+
);
20+
}
21+
22+
public function testIsAnException()
23+
{
24+
$this->assertInstanceOf('\Exception', $this->exception);
25+
}
26+
27+
public function testAccessors()
28+
{
29+
$this->assertEquals('Tango is down, I repeat...', $this->exception->getMessage());
30+
$this->assertEquals(array('foo' => 'fighter'), $this->exception->getItem());
31+
}
32+
}

Step/AbstractStep.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Oro\Bundle\BatchBundle\Job\JobInterruptedException;
1111
use Oro\Bundle\BatchBundle\Entity\StepExecution;
1212
use Oro\Bundle\BatchBundle\Event\StepExecutionEvent;
13+
use Oro\Bundle\BatchBundle\Event\InvalidItemEvent;
1314
use Oro\Bundle\BatchBundle\Event\EventInterface;
1415

1516
/**
@@ -47,7 +48,7 @@ public function __construct($name)
4748
/**
4849
* Set the event dispatcher
4950
*
50-
* @param EventDispatcherInterface $eventDispatcher
51+
* @param EventDispatcherInterface $eventDispatcher
5152
* @return AbstractStep
5253
*/
5354
public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
@@ -60,7 +61,7 @@ public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
6061
/**
6162
* Public setter for {@link JobRepositoryInterface}.
6263
*
63-
* @param JobRepositoryInterface $jobRepository jobRepository is a mandatory dependence (no default).
64+
* @param JobRepositoryInterface $jobRepository jobRepository is a mandatory dependence (no default).
6465
* @return AbstractStep
6566
*/
6667
public function setJobRepository(JobRepositoryInterface $jobRepository)
@@ -89,7 +90,7 @@ public function getName()
8990
/**
9091
* Set the name property
9192
*
92-
* @param string $name
93+
* @param string $name
9394
* @return AbstractStep
9495
*/
9596
public function setName($name)
@@ -103,7 +104,7 @@ public function setName($name)
103104
* Extension point for subclasses to execute business logic. Subclasses should set the {@link ExitStatus} on the
104105
* {@link StepExecution} before returning.
105106
*
106-
* @param StepExecution $stepExecution the current step context
107+
* @param StepExecution $stepExecution the current step context
107108
* @throws \Exception
108109
*/
109110
abstract protected function doExecute(StepExecution $stepExecution);
@@ -174,7 +175,7 @@ final public function execute(StepExecution $stepExecution)
174175

175176
/**
176177
* Determine the step status based on the exception.
177-
* @param \Exception $e
178+
* @param \Exception $e
178179
* @return int
179180
*/
180181
private static function determineBatchStatus(\Exception $e)
@@ -190,7 +191,7 @@ private static function determineBatchStatus(\Exception $e)
190191
* Default mapping from throwable to {@link ExitStatus}. Clients can modify the exit code using a
191192
* {@link StepExecutionListener}.
192193
*
193-
* @param \Exception $e the cause of the failure
194+
* @param \Exception $e the cause of the failure
194195
* @return ExitStatus {@link ExitStatus}
195196
*/
196197
private function getDefaultExitStatusForFailure(\Exception $e)
@@ -218,6 +219,12 @@ protected function dispatchStepExecutionEvent($eventName, StepExecution $stepExe
218219
$this->dispatch($eventName, $event);
219220
}
220221

222+
protected function dispatchInvalidItemEvent($class, $reason, array $item)
223+
{
224+
$event = new InvalidItemEvent($class, $reason, $item);
225+
$this->dispatch(EventInterface::INVALID_ITEM, $event);
226+
}
227+
221228
/**
222229
* Generic batch event dispatcher
223230
*

Step/ItemStep.php

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
namespace Oro\Bundle\BatchBundle\Step;
44

55
use Symfony\Component\Validator\Constraints as Assert;
6+
use Oro\Bundle\BatchBundle\Step\StepExecutionAwareInterface;
67
use Oro\Bundle\BatchBundle\Entity\StepExecution;
8+
use Oro\Bundle\BatchBundle\Item\AbstractConfigurableStepElement;
79
use Oro\Bundle\BatchBundle\Item\ItemReaderInterface;
810
use Oro\Bundle\BatchBundle\Item\ItemProcessorInterface;
911
use Oro\Bundle\BatchBundle\Item\ItemWriterInterface;
10-
use Oro\Bundle\BatchBundle\Event\EventInterface;
11-
use Oro\Bundle\BatchBundle\Item\AbstractConfigurableStepElement;
12-
use Oro\Bundle\BatchBundle\Step\StepExecutionAwareInterface;
12+
use Oro\Bundle\BatchBundle\Item\InvalidItemException;
1313

1414
/**
1515
* Basic step implementation that read items, process them and write them
@@ -161,33 +161,74 @@ public function setConfiguration(array $config)
161161
*/
162162
public function doExecute(StepExecution $stepExecution)
163163
{
164-
$itemsToWrite = array();
165-
$writeCount = 0;
164+
$itemsToWrite = array();
165+
$writeCount = 0;
166+
$stopExecution = false;
166167

167168
$this->initializeStepComponents($stepExecution);
168169

169-
while (($item = $this->reader->read()) !== null) {
170-
if (false === $item) {
171-
$this->dispatchStepExecutionEvent(EventInterface::INVALID_READER_EXECUTION, $stepExecution);
170+
while (!$stopExecution) {
171+
// Reading
172+
try {
173+
if (null === $item = $this->reader->read()) {
174+
$stopExecution = true;
175+
176+
continue;
177+
}
178+
} catch (InvalidItemException $e) {
179+
$this->dispatchInvalidItemEvent(
180+
get_class($this->reader),
181+
$e->getMessage(),
182+
$e->getItem()
183+
);
184+
172185
continue;
173186
}
174187

175-
if (null !== $processedItem = $this->processor->process($item)) {
176-
if (false === $processedItem) {
188+
// Processing
189+
try {
190+
if (null === $processedItem = $this->processor->process($item)) {
177191
continue;
178192
}
179-
$itemsToWrite[] = $processedItem;
180-
$writeCount++;
181-
if (0 === $writeCount % $this->batchSize) {
193+
} catch (InvalidItemException $e) {
194+
$this->dispatchInvalidItemEvent(
195+
get_class($this->processor),
196+
$e->getMessage(),
197+
$e->getItem()
198+
);
199+
200+
continue;
201+
}
202+
203+
// Writing
204+
$itemsToWrite[] = $processedItem;
205+
if (0 === ++$writeCount % $this->batchSize) {
206+
try {
182207
$this->writer->write($itemsToWrite);
183208
$itemsToWrite = array();
209+
} catch (InvalidItemException $e) {
210+
$this->dispatchInvalidItemEvent(
211+
get_class($this->processor),
212+
$e->getMessage(),
213+
$e->getItem()
214+
);
215+
216+
continue;
184217
}
185218
}
186219
}
187220

188221
if (count($itemsToWrite) > 0) {
189-
$this->writer->write($itemsToWrite);
190-
$itemsToWrite = array();
222+
try {
223+
$this->writer->write($itemsToWrite);
224+
$itemsToWrite = array();
225+
} catch (InvalidItemException $e) {
226+
$this->dispatchInvalidItemEvent(
227+
get_class($this->processor),
228+
$e->getMessage(),
229+
$e->getItem()
230+
);
231+
}
191232
}
192233
}
193234

0 commit comments

Comments
 (0)