Files
wiki_travel_site/app/Jobs/FetchAttractionsJob.php
2026-04-28 16:10:27 +03:00

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(),
]
);
}
}