Given more semantic cases in which a visit cannot be located

This commit is contained in:
Alejandro Celaya 2019-02-26 21:39:45 +01:00
parent c70077c525
commit 2d1d7357a3
4 changed files with 49 additions and 6 deletions

View file

@ -83,14 +83,14 @@ class ProcessVisitsCommand extends Command
'<comment>Ignored visit with no IP address</comment>',
OutputInterface::VERBOSITY_VERBOSE
);
throw new IpCannotBeLocatedException('Ignored visit with no IP address');
throw IpCannotBeLocatedException::forEmptyAddress();
}
$ipAddr = $visit->getRemoteAddr();
$this->output->write(sprintf('Processing IP <fg=blue>%s</>', $ipAddr));
if ($ipAddr === IpAddress::LOCALHOST) {
$this->output->writeln(' [<comment>Ignored localhost address</comment>]');
throw new IpCannotBeLocatedException('Ignored localhost address');
throw IpCannotBeLocatedException::forLocalhost();
}
try {
@ -101,7 +101,7 @@ class ProcessVisitsCommand extends Command
$this->getApplication()->renderException($e, $this->output);
}
throw new IpCannotBeLocatedException('An error occurred while locating IP', $e->getCode(), $e);
throw IpCannotBeLocatedException::forError($e);
}
}
}

View file

@ -3,6 +3,43 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Core\Exception;
use Throwable;
class IpCannotBeLocatedException extends RuntimeException
{
/** @var bool */
private $isNonLocatableAddress;
public function __construct(
bool $isNonLocatableAddress,
string $message,
int $code = 0,
?Throwable $previous = null
) {
$this->isNonLocatableAddress = $isNonLocatableAddress;
parent::__construct($message, $code, $previous);
}
public static function forEmptyAddress(): self
{
return new self(true, 'Ignored visit with no IP address');
}
public static function forLocalhost(): self
{
return new self(true, 'Ignored localhost address');
}
public static function forError(Throwable $e): self
{
return new self(false, 'An error occurred while locating IP', $e->getCode(), $e);
}
/**
* Tells if this error belongs to an address that will never be possible locate
*/
public function isNonLocatableAddress(): bool
{
return $this->isNonLocatableAddress;
}
}

View file

@ -30,12 +30,18 @@ class VisitService implements VisitServiceInterface
foreach ($results as $visit) {
$count++;
try {
/** @var Location $location */
$location = $geolocateVisit($visit);
} catch (IpCannotBeLocatedException $e) {
// Skip if the visit's IP could not be located
continue;
if (!$e->isNonLocatableAddress()) {
// Skip if the visit's IP could not be located because of an error
continue;
}
// If the IP address is non-locatable, locate it as empty to prevent next processes to pick it again
$location = Location::emptyInstance();
}
$location = new VisitLocation($location);

View file

@ -89,7 +89,7 @@ class VisitServiceTest extends TestCase
});
$this->visitService->locateUnlocatedVisits(function () {
throw new IpCannotBeLocatedException('Cannot be located');
throw new IpCannotBeLocatedException(false, 'Cannot be located');
});
$findUnlocatedVisits->shouldHaveBeenCalledOnce();