diff --git a/src/Porter.php b/src/Porter.php index d588f8d..961ecfd 100644 --- a/src/Porter.php +++ b/src/Porter.php @@ -96,7 +96,12 @@ private function fetch(ProviderResource $resource, CacheAdvice $cacheAdvice, $fe if (($records = \ScriptFUSION\Retry\retry( $fetchAttempts, function () use ($provider, $resource) { - return $provider->fetch($resource); + if (($records = $provider->fetch($resource)) instanceof \Iterator) { + // Force generator to run until first yield to provoke an exception. + $records->valid(); + } + + return $records; }, function (\Exception $exception) use ($fetchExceptionHandler) { // Throw exception if unrecoverable. diff --git a/test/Integration/Porter/PorterTest.php b/test/Integration/Porter/PorterTest.php index d286648..3c1a1e6 100644 --- a/test/Integration/Porter/PorterTest.php +++ b/test/Integration/Porter/PorterTest.php @@ -300,6 +300,23 @@ public function testCustomFetchExceptionHandler() $this->porter->import($this->specification); } + /** + * Tests that when a generator throws a recoverable exception before the first yield, the fetch is retried. + * + * Note this does not support cases where exceptions may be thrown in subsequent iterations. + */ + public function testGeneratorException() + { + $this->provider->shouldReceive('fetch')->once()->andReturnUsing(function () { + throw new RecoverableConnectorException; + + yield; + }); + + $this->setExpectedException(FailingTooHardException::class, '1'); + $this->porter->import($this->specification->setMaxFetchAttempts(1)); + } + #endregion public function testFilter()