From ed859767a816726a68e1b3914c61e7b49cfacb7e Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Thu, 2 Aug 2018 23:02:48 +0200 Subject: [PATCH] Updated IpLocation resolver to be able to provide limits in order to apply sleeps --- .../Command/Visit/ProcessVisitsCommand.php | 12 +++++++++++ .../Visit/ProcessVisitsCommandTest.php | 2 ++ .../src/Service/IpApiLocationResolver.php | 20 +++++++++++++++++++ .../Service/IpLocationResolverInterface.php | 14 +++++++++++++ 4 files changed, 48 insertions(+) diff --git a/module/CLI/src/Command/Visit/ProcessVisitsCommand.php b/module/CLI/src/Command/Visit/ProcessVisitsCommand.php index 81200e22..b858546d 100644 --- a/module/CLI/src/Command/Visit/ProcessVisitsCommand.php +++ b/module/CLI/src/Command/Visit/ProcessVisitsCommand.php @@ -55,6 +55,7 @@ class ProcessVisitsCommand extends Command $io = new SymfonyStyle($input, $output); $visits = $this->visitService->getUnlocatedVisits(); + $count = 0; foreach ($visits as $visit) { $ipAddr = $visit->getRemoteAddr(); $io->write(\sprintf('%s %s', $this->translator->translate('Processing IP'), $ipAddr)); @@ -65,6 +66,7 @@ class ProcessVisitsCommand extends Command continue; } + $count++; try { $result = $this->ipLocationResolver->resolveIpLocation($ipAddr); @@ -85,6 +87,16 @@ class ProcessVisitsCommand extends Command $this->getApplication()->renderException($e, $output); } } + + if ($count === $this->ipLocationResolver->getApiLimit()) { + $count = 0; + $seconds = $this->ipLocationResolver->getApiInterval(); + $io->note(\sprintf( + $this->translator->translate('IP location resolver limit reached. Waiting %s seconds...'), + $seconds + )); + \sleep($seconds); + } } $io->success($this->translator->translate('Finished processing all IPs')); diff --git a/module/CLI/test/Command/Visit/ProcessVisitsCommandTest.php b/module/CLI/test/Command/Visit/ProcessVisitsCommandTest.php index bc62124f..ae36de22 100644 --- a/module/CLI/test/Command/Visit/ProcessVisitsCommandTest.php +++ b/module/CLI/test/Command/Visit/ProcessVisitsCommandTest.php @@ -33,6 +33,8 @@ class ProcessVisitsCommandTest extends TestCase { $this->visitService = $this->prophesize(VisitService::class); $this->ipResolver = $this->prophesize(IpApiLocationResolver::class); + $this->ipResolver->getApiLimit()->willReturn(10000000000); + $command = new ProcessVisitsCommand( $this->visitService->reveal(), $this->ipResolver->reveal(), diff --git a/module/Common/src/Service/IpApiLocationResolver.php b/module/Common/src/Service/IpApiLocationResolver.php index 9787770c..d801a2e8 100644 --- a/module/Common/src/Service/IpApiLocationResolver.php +++ b/module/Common/src/Service/IpApiLocationResolver.php @@ -48,4 +48,24 @@ class IpApiLocationResolver implements IpLocationResolverInterface 'time_zone' => $entry['timezone'] ?? '', ]; } + + /** + * Returns the interval in seconds that needs to be waited when the API limit is reached + * + * @return int + */ + public function getApiInterval(): int + { + return 65; // ip-api interval is 1 minute. Return 5 extra seconds just in case + } + + /** + * Returns the limit of requests that can be performed to the API in a specific interval, or null if no limit exists + * + * @return int|null + */ + public function getApiLimit(): ?int + { + return 145; // ip-api limit is 150 requests per minute. Leave 5 less requests just in case + } } diff --git a/module/Common/src/Service/IpLocationResolverInterface.php b/module/Common/src/Service/IpLocationResolverInterface.php index fc1f07a3..98099946 100644 --- a/module/Common/src/Service/IpLocationResolverInterface.php +++ b/module/Common/src/Service/IpLocationResolverInterface.php @@ -13,4 +13,18 @@ interface IpLocationResolverInterface * @throws WrongIpException */ public function resolveIpLocation(string $ipAddress): array; + + /** + * Returns the interval in seconds that needs to be waited when the API limit is reached + * + * @return int + */ + public function getApiInterval(): int; + + /** + * Returns the limit of requests that can be performed to the API in a specific interval, or null if no limit exists + * + * @return int|null + */ + public function getApiLimit(): ?int; }