Introduzione
Supponiamo che tu abbia un design simile nella tua applicazione:
- application (laravel)
- web scraper (used by application)
- query builder (used by web scraper)
L'applicazione è ciò che effettivamente usa il Web Scraper per recuperare i dati dal web, tuttavia poiché utilizziamo il Web Scraper come motore di ricerca , costruiamo la stringa di query utilizzata dal Web Scraper basato sull'input dell'utente.
Il Web Scraper è la libreria che si occupa effettivamente dell'estrazione e dell'analisi dei file HTML presi dai siti in cui lavoriamo.
Query Builder utilizza alcune API remote (ad esempio google maps per le coordinate basate sull'input dell'utente) da utilizzare nel Web Scraper.
Esempio di codice
class WebsiteScraper
{
public function city($city)
{
$this->parameters['city'] = CityIdentifierFactory::retrieve($city);
}
}
class CityIdentifier
{
const API_URL = "http://maps.google.com/maps/api/geocode/json";
public function __construct(\GuzzleHttp\Client $client)
{
$this->client = $client;
}
public function retrieve($city)
{
try
{
$coordinates = $this->getCoordinates($city);
if (count($coordinates) <= 0) {
return [];
}
return $coordinates;
} catch (Exception $e) {
throw new QueryBuilderCityFetchingException(
"Whoops! Something wrong happened."
);
}
}
private function getCoordinates($city)
{
$response = $this->client->get(self::API_URL, [
'query' => [
'address' => $city,
'region' => 'IT'
]
]);
$body = json_decode($response->getBody()->getContents());
return [[
'city' => $city,
'lat' => $body->results[0]->geometry->location->lat,
'lng' => $body->results[0]->geometry->location->lng,
'location' => $city
]];
}
}
class CityIdentifierFactory
{
public static function retrieveFromDisk($name)
{
$identifier = new FilesystemCityIdentifier(__DIR__ . "/../../assets/provinces.json");
return $identifier->retrieve($name);
}
public static function retrieve($name)
{
$identifier = new CityIdentifier(new Client);
return $identifier->retrieve($name);
}
}
Problema
Il problema è che il Web Scraper viene eseguito migliaia di volte al giorno e le API di Google Maps hanno dei limiti che non dovremmo raggiungere (anche se li abbiamo già raggiunti! :(). Vorrei implementare un livello di memorizzazione nella cache in il componente CityIdentifier di Query Builder, in modo da evitare di fare migliaia di query relative alla stessa città.
Domanda
Dove devo implementare questo livello di memorizzazione nella cache, sapendo che tutte queste cose verranno inserite per iniezione di dipendenza in Laravel (4.2)?
Dovrebbe essere nel raschietto Web, nel generatore di query o nel componente CityIdentifier effettivo?
Dove dovrebbe essere salvata la cache? In una cartella interna del generatore di query o in una cartella di applicazioni configurata nella libreria?