127 lines
3.8 KiB
PHP
127 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace App\Jobs;
|
|
|
|
use App\Models\City;
|
|
use App\Models\Attraction;
|
|
use App\Services\OpenTripMapService;
|
|
use App\Services\OverpassService;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Queue\Queueable;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class FetchAttractionsJob implements ShouldQueue
|
|
{
|
|
use Queueable;
|
|
|
|
public int $tries = 3;
|
|
public int $timeout = 120;
|
|
|
|
/**
|
|
* Create a new job instance.
|
|
*/
|
|
public function __construct(
|
|
public City $city,
|
|
public bool $forceRefresh = false
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Execute the job.
|
|
*/
|
|
public function handle(
|
|
OpenTripMapService $openTripMapService,
|
|
OverpassService $overpassService
|
|
): void {
|
|
try {
|
|
// Check if we need to refresh
|
|
if (!$this->forceRefresh) {
|
|
$lastAttraction = $this->city->attractions()
|
|
->orderBy('cached_at', 'desc')
|
|
->first();
|
|
|
|
if ($lastAttraction && $lastAttraction->cached_at) {
|
|
$cacheAge = now()->diffInDays($lastAttraction->cached_at);
|
|
$cacheTtl = config('services.opentripmap.cache_ttl', 7);
|
|
|
|
if ($cacheAge < $cacheTtl) {
|
|
Log::info("Attractions data is still fresh, skipping fetch", [
|
|
'city_id' => $this->city->id,
|
|
'cache_age' => $cacheAge,
|
|
]);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$this->city->latitude || !$this->city->longitude) {
|
|
Log::warning("City coordinates not set, cannot fetch attractions", [
|
|
'city_id' => $this->city->id,
|
|
]);
|
|
return;
|
|
}
|
|
|
|
$attractionsCreated = 0;
|
|
|
|
// Fetch from OpenTripMap
|
|
$openTripMapData = $openTripMapService->getAttractions(
|
|
$this->city->latitude,
|
|
$this->city->longitude
|
|
);
|
|
|
|
foreach ($openTripMapData as $data) {
|
|
$this->createOrUpdateAttraction($data, 'opentripmap');
|
|
$attractionsCreated++;
|
|
}
|
|
|
|
// Fetch from Overpass
|
|
$overpassData = $overpassService->getPointsOfInterest(
|
|
$this->city->latitude,
|
|
$this->city->longitude
|
|
);
|
|
|
|
foreach ($overpassData as $data) {
|
|
$this->createOrUpdateAttraction($data, 'overpass');
|
|
$attractionsCreated++;
|
|
}
|
|
|
|
Log::info("Attractions fetched successfully", [
|
|
'city_id' => $this->city->id,
|
|
'city_name' => $this->city->name,
|
|
'attractions_created' => $attractionsCreated,
|
|
]);
|
|
} catch (\Exception $e) {
|
|
Log::error("Error in FetchAttractionsJob", [
|
|
'city_id' => $this->city->id,
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create or update an attraction
|
|
*/
|
|
private function createOrUpdateAttraction(array $data, string $source): void
|
|
{
|
|
Attraction::updateOrCreate(
|
|
[
|
|
'city_id' => $this->city->id,
|
|
'source' => $source,
|
|
'source_id' => $data['source_id'],
|
|
],
|
|
[
|
|
'name' => $data['name'],
|
|
'description' => $data['description'] ?? null,
|
|
'latitude' => $data['latitude'],
|
|
'longitude' => $data['longitude'],
|
|
'category' => $data['category'] ?? 'other',
|
|
'rating' => $data['rating'] ?? null,
|
|
'image_url' => $data['image_url'] ?? null,
|
|
'cached_at' => now(),
|
|
]
|
|
);
|
|
}
|
|
}
|