Skip to content

Commit 6d16020

Browse files
committed
Moved fetch attempts and exception handler from Porter -> ImportSpecification.
1 parent 8e69257 commit 6d16020

File tree

3 files changed

+80
-65
lines changed

3 files changed

+80
-65
lines changed

src/Porter.php

Lines changed: 11 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,12 @@
1616
use ScriptFUSION\Porter\Provider\Resource\ProviderResource;
1717
use ScriptFUSION\Porter\Specification\ImportSpecification;
1818
use ScriptFUSION\Porter\Transform\Transformer;
19-
use ScriptFUSION\Retry\ExceptionHandler\ExponentialBackoffExceptionHandler;
2019

2120
/**
2221
* Imports data according to an ImportSpecification.
2322
*/
2423
class Porter
2524
{
26-
const DEFAULT_FETCH_ATTEMPTS = 5;
27-
2825
/**
2926
* @var Provider[]
3027
*/
@@ -35,16 +32,6 @@ class Porter
3532
*/
3633
private $providerFactory;
3734

38-
/**
39-
* @var int
40-
*/
41-
private $maxFetchAttempts = self::DEFAULT_FETCH_ATTEMPTS;
42-
43-
/**
44-
* @var callable
45-
*/
46-
private $fetchExceptionHandler;
47-
4835
/**
4936
* Imports data according to the design of the specified import specification.
5037
*
@@ -57,7 +44,13 @@ class Porter
5744
public function import(ImportSpecification $specification)
5845
{
5946
$specification = clone $specification;
60-
$records = $this->fetch($specification->getResource(), $specification->getCacheAdvice());
47+
48+
$records = $this->fetch(
49+
$specification->getResource(),
50+
$specification->getCacheAdvice(),
51+
$specification->getMaxFetchAttempts(),
52+
$specification->getFetchExceptionHandler()
53+
);
6154

6255
if (!$records instanceof ProviderRecords) {
6356
$records = $this->createProviderRecords($records, $specification->getResource());
@@ -94,24 +87,24 @@ public function importOne(ImportSpecification $specification)
9487
return $one;
9588
}
9689

97-
private function fetch(ProviderResource $resource, CacheAdvice $cacheAdvice = null)
90+
private function fetch(ProviderResource $resource, CacheAdvice $cacheAdvice, $fetchAttempts, $fetchExceptionHandler)
9891
{
9992
$provider = $this->getProvider($resource->getProviderClassName(), $resource->getProviderTag());
10093

10194
$this->applyCacheAdvice($provider, $cacheAdvice);
10295

10396
if (($records = \ScriptFUSION\Retry\retry(
104-
$this->getMaxFetchAttempts(),
97+
$fetchAttempts,
10598
function () use ($provider, $resource) {
10699
return $provider->fetch($resource);
107100
},
108-
function (\Exception $exception) {
101+
function (\Exception $exception) use ($fetchExceptionHandler) {
109102
// Throw exception if unrecoverable.
110103
if (!$exception instanceof RecoverableConnectorException) {
111104
throw $exception;
112105
}
113106

114-
call_user_func($this->getFetchExceptionHandler(), $exception);
107+
$fetchExceptionHandler($exception);
115108
}
116109
)) instanceof \Iterator) {
117110
return $records;
@@ -266,44 +259,4 @@ private function getOrCreateProviderFactory()
266259
{
267260
return $this->providerFactory ?: $this->providerFactory = new ProviderFactory;
268261
}
269-
270-
/**
271-
* Gets the maximum number of fetch attempts per import.
272-
*
273-
* @return int
274-
*/
275-
public function getMaxFetchAttempts()
276-
{
277-
return $this->maxFetchAttempts;
278-
}
279-
280-
/**
281-
* Sets the maximum number of fetch attempts per import.
282-
*
283-
* @param int $attempts Maximum fetch attempts.
284-
*
285-
* @return $this
286-
*/
287-
public function setMaxFetchAttempts($attempts)
288-
{
289-
$this->maxFetchAttempts = max(1, $attempts|0);
290-
291-
return $this;
292-
}
293-
294-
/**
295-
* @return callable
296-
*/
297-
private function getFetchExceptionHandler()
298-
{
299-
return $this->fetchExceptionHandler ?: $this->fetchExceptionHandler = new ExponentialBackoffExceptionHandler;
300-
}
301-
302-
/**
303-
* @param callable $fetchExceptionHandler
304-
*/
305-
public function setFetchExceptionHandler(callable $fetchExceptionHandler)
306-
{
307-
$this->fetchExceptionHandler = $fetchExceptionHandler;
308-
}
309262
}

src/Specification/ImportSpecification.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
use ScriptFUSION\Porter\Cache\CacheAdvice;
55
use ScriptFUSION\Porter\Provider\Resource\ProviderResource;
66
use ScriptFUSION\Porter\Transform\Transformer;
7+
use ScriptFUSION\Retry\ExceptionHandler\ExponentialBackoffExceptionHandler;
78

89
/**
910
* Specifies which resource to import and how the data should be transformed.
1011
*/
1112
class ImportSpecification
1213
{
14+
const DEFAULT_FETCH_ATTEMPTS = 5;
15+
1316
/**
1417
* @var ProviderResource
1518
*/
@@ -35,6 +38,16 @@ class ImportSpecification
3538
*/
3639
private $defaultCacheAdvice;
3740

41+
/**
42+
* @var int
43+
*/
44+
private $maxFetchAttempts = self::DEFAULT_FETCH_ATTEMPTS;
45+
46+
/**
47+
* @var callable
48+
*/
49+
private $fetchExceptionHandler;
50+
3851
public function __construct(ProviderResource $resource)
3952
{
4053
$this->resource = $resource;
@@ -56,6 +69,7 @@ function (Transformer $transformer) {
5669
));
5770

5871
is_object($this->context) && $this->context = clone $this->context;
72+
is_object($this->fetchExceptionHandler) && $this->fetchExceptionHandler = clone $this->fetchExceptionHandler;
5973
}
6074

6175
/**
@@ -162,4 +176,52 @@ final public function setCacheAdvice(CacheAdvice $cacheAdvice)
162176

163177
return $this;
164178
}
179+
180+
/**
181+
* Gets the maximum number of fetch attempts per import.
182+
*
183+
* @return int Maximum fetch attempts.
184+
*/
185+
final public function getMaxFetchAttempts()
186+
{
187+
return $this->maxFetchAttempts;
188+
}
189+
190+
/**
191+
* Sets the maximum number of fetch attempts per import.
192+
*
193+
* @param int $attempts Maximum fetch attempts.
194+
*
195+
* @return $this
196+
*/
197+
final public function setMaxFetchAttempts($attempts)
198+
{
199+
$this->maxFetchAttempts = max(1, $attempts|0);
200+
201+
return $this;
202+
}
203+
204+
/**
205+
* Gets the exception handler invoked each time a fetch attempt fails.
206+
*
207+
* @return callable Exception handler.
208+
*/
209+
final public function getFetchExceptionHandler()
210+
{
211+
return $this->fetchExceptionHandler ?: $this->fetchExceptionHandler = new ExponentialBackoffExceptionHandler;
212+
}
213+
214+
/**
215+
* Sets the exception handler invoked each time a fetch attempt fails.
216+
*
217+
* @param callable $fetchExceptionHandler Exception handler.
218+
*
219+
* @return $this
220+
*/
221+
final public function setFetchExceptionHandler(callable $fetchExceptionHandler)
222+
{
223+
$this->fetchExceptionHandler = $fetchExceptionHandler;
224+
225+
return $this;
226+
}
165227
}

test/Integration/Porter/PorterTest.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -257,23 +257,23 @@ public function testOneTry()
257257
$this->provider->shouldReceive('fetch')->once()->andThrow(RecoverableConnectorException::class);
258258

259259
$this->setExpectedException(FailingTooHardException::class, '1');
260-
$this->porter->setMaxFetchAttempts(1)->import($this->specification);
260+
$this->porter->import($this->specification->setMaxFetchAttempts(1));
261261
}
262262

263263
public function testDerivedRecoverableException()
264264
{
265265
$this->provider->shouldReceive('fetch')->once()->andThrow(\Mockery::mock(RecoverableConnectorException::class));
266266

267267
$this->setExpectedException(FailingTooHardException::class);
268-
$this->porter->setMaxFetchAttempts(1)->import($this->specification);
268+
$this->porter->import($this->specification->setMaxFetchAttempts(1));
269269
}
270270

271271
public function testDefaultTries()
272272
{
273-
$this->provider->shouldReceive('fetch')->times(Porter::DEFAULT_FETCH_ATTEMPTS)
273+
$this->provider->shouldReceive('fetch')->times(ImportSpecification::DEFAULT_FETCH_ATTEMPTS)
274274
->andThrow(RecoverableConnectorException::class);
275275

276-
$this->setExpectedException(FailingTooHardException::class, (string)Porter::DEFAULT_FETCH_ATTEMPTS);
276+
$this->setExpectedException(FailingTooHardException::class, (string)ImportSpecification::DEFAULT_FETCH_ATTEMPTS);
277277
$this->porter->import($this->specification);
278278
}
279279

@@ -287,13 +287,13 @@ public function testUnrecoverableException()
287287

288288
public function testCustomFetchExceptionHandler()
289289
{
290-
$this->porter->setFetchExceptionHandler(
290+
$this->specification->setFetchExceptionHandler(
291291
\Mockery::mock(ExponentialBackoffExceptionHandler::class)
292292
->shouldReceive('__invoke')
293-
->times(Porter::DEFAULT_FETCH_ATTEMPTS - 1)
293+
->times(ImportSpecification::DEFAULT_FETCH_ATTEMPTS - 1)
294294
->getMock()
295295
);
296-
$this->provider->shouldReceive('fetch')->times(Porter::DEFAULT_FETCH_ATTEMPTS)
296+
$this->provider->shouldReceive('fetch')->times(ImportSpecification::DEFAULT_FETCH_ATTEMPTS)
297297
->andThrow(RecoverableConnectorException::class);
298298

299299
$this->setExpectedException(FailingTooHardException::class);

0 commit comments

Comments
 (0)