fix: remove redundant insurance hydration, cache snapshots and files map
This commit is contained in:
@@ -7,7 +7,6 @@ namespace App\Service;
|
|||||||
use App\BusProNet\ApiClient;
|
use App\BusProNet\ApiClient;
|
||||||
use App\BusProNet\Exception\ApiClientException;
|
use App\BusProNet\Exception\ApiClientException;
|
||||||
use App\BusProNet\Model\BaseData;
|
use App\BusProNet\Model\BaseData;
|
||||||
use App\BusProNet\Model\Insurance;
|
|
||||||
use App\BusProNet\Model\Notification;
|
use App\BusProNet\Model\Notification;
|
||||||
use App\BusProNet\Model\ServiceAvailabilityResponse;
|
use App\BusProNet\Model\ServiceAvailabilityResponse;
|
||||||
use App\BusProNet\Model\Travel;
|
use App\BusProNet\Model\Travel;
|
||||||
@@ -38,6 +37,9 @@ class TravelDataService
|
|||||||
private const int AVAILABILITY_CACHE_TTL = 600;
|
private const int AVAILABILITY_CACHE_TTL = 600;
|
||||||
private const int MUTABILITY_CACHE_TTL = 300;
|
private const int MUTABILITY_CACHE_TTL = 300;
|
||||||
|
|
||||||
|
/** @var array<int, array<string, mixed>>|null */
|
||||||
|
private ?array $filesMapCache = null;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly TravelLoader $travelLoader,
|
private readonly TravelLoader $travelLoader,
|
||||||
private readonly HotelLoader $hotelLoader,
|
private readonly HotelLoader $hotelLoader,
|
||||||
@@ -147,7 +149,6 @@ class TravelDataService
|
|||||||
|
|
||||||
if (null !== $travel) {
|
if (null !== $travel) {
|
||||||
$this->patchInsuranceData($travel);
|
$this->patchInsuranceData($travel);
|
||||||
$this->hydrateInsurancePackageRelationships($travel->insurances);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $travel;
|
return $travel;
|
||||||
@@ -275,6 +276,9 @@ class TravelDataService
|
|||||||
'travelId' => $result->id,
|
'travelId' => $result->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$this->patchInsuranceData($result);
|
||||||
|
$this->travelSnapshotService->upsertFromTravel($result);
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
} catch (ApiClientException $e) {
|
} catch (ApiClientException $e) {
|
||||||
$this->logger->error('Failed to load travel data from API', [
|
$this->logger->error('Failed to load travel data from API', [
|
||||||
@@ -508,6 +512,10 @@ class TravelDataService
|
|||||||
*/
|
*/
|
||||||
public function generateFilesMap(): array
|
public function generateFilesMap(): array
|
||||||
{
|
{
|
||||||
|
if (null !== $this->filesMapCache) {
|
||||||
|
return $this->filesMapCache;
|
||||||
|
}
|
||||||
|
|
||||||
$mapping = [];
|
$mapping = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -537,6 +545,8 @@ class TravelDataService
|
|||||||
'count' => count($mapping),
|
'count' => count($mapping),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$this->filesMapCache = $mapping;
|
||||||
|
|
||||||
return $mapping;
|
return $mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -792,35 +802,4 @@ class TravelDataService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reconstructs containedInsurances arrays for insurance packages.
|
|
||||||
*
|
|
||||||
* Insurance packages reference other insurances via containedInsuranceIds.
|
|
||||||
* After deserialization, the containedInsurances array is empty due to
|
|
||||||
* circular reference prevention. This method rebuilds those relationships.
|
|
||||||
*
|
|
||||||
* @param array<Insurance> $insurances All insurances including packages
|
|
||||||
*/
|
|
||||||
private function hydrateInsurancePackageRelationships(array $insurances): void
|
|
||||||
{
|
|
||||||
// Build lookup map of all insurances by ID (includes complementary insurances)
|
|
||||||
$insuranceById = [];
|
|
||||||
foreach ($insurances as $insurance) {
|
|
||||||
$insuranceById[$insurance->id] = $insurance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconstruct containedInsurances for each package
|
|
||||||
foreach ($insurances as $insurance) {
|
|
||||||
if (!$insurance->package || empty($insurance->containedInsuranceIds)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$insurance->containedInsurances = [];
|
|
||||||
foreach ($insurance->containedInsuranceIds as $containedId) {
|
|
||||||
if (isset($insuranceById[$containedId])) {
|
|
||||||
$insurance->containedInsurances[] = $insuranceById[$containedId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ class TravelDataServiceTest extends TestCase
|
|||||||
$this->assertSame($travel, $result);
|
$this->assertSame($travel, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetTravelDataFromLocalHydratesInsurancePackagesFromLoaderAfterSnapshotLoad(): void
|
public function testGetTravelDataFromLocalReplacesSnapshotInsurancesWithLoaderData(): void
|
||||||
{
|
{
|
||||||
$dateId = 12345;
|
$dateId = 12345;
|
||||||
$hotelId = 67890;
|
$hotelId = 67890;
|
||||||
@@ -335,7 +335,8 @@ class TravelDataServiceTest extends TestCase
|
|||||||
$package->id = '20';
|
$package->id = '20';
|
||||||
$package->package = true;
|
$package->package = true;
|
||||||
$package->containedInsuranceIds = ['10'];
|
$package->containedInsuranceIds = ['10'];
|
||||||
$package->containedInsurances = [];
|
// InsuranceParser populates containedInsurances at parse time; loadAll() returns hydrated data.
|
||||||
|
$package->containedInsurances = [$individual];
|
||||||
|
|
||||||
$this->travelSnapshotService
|
$this->travelSnapshotService
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
@@ -396,13 +397,11 @@ class TravelDataServiceTest extends TestCase
|
|||||||
$this->assertSame($travel, $result);
|
$this->assertSame($travel, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetTravelDataFromLocalRehydratesInsurancePackagesFromXmlFallback(): void
|
public function testGetTravelDataFromLocalAttachesLoaderInsurancesFromXmlFallback(): void
|
||||||
{
|
{
|
||||||
$dateId = 12345;
|
$dateId = 12345;
|
||||||
$hotelId = 67890;
|
$hotelId = 67890;
|
||||||
|
|
||||||
// InsuranceLoader supplies the canonical insurance list for local reads; the package's
|
|
||||||
// containedInsurances starts empty and is rebuilt after hydration.
|
|
||||||
$individual = new Insurance();
|
$individual = new Insurance();
|
||||||
$individual->id = '10';
|
$individual->id = '10';
|
||||||
$individual->package = false;
|
$individual->package = false;
|
||||||
@@ -411,7 +410,8 @@ class TravelDataServiceTest extends TestCase
|
|||||||
$package->id = '20';
|
$package->id = '20';
|
||||||
$package->package = true;
|
$package->package = true;
|
||||||
$package->containedInsuranceIds = ['10'];
|
$package->containedInsuranceIds = ['10'];
|
||||||
$package->containedInsurances = [];
|
// InsuranceParser populates containedInsurances at parse time; loadAll() returns hydrated data.
|
||||||
|
$package->containedInsurances = [$individual];
|
||||||
|
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$travel->id = $dateId;
|
$travel->id = $dateId;
|
||||||
|
|||||||
Reference in New Issue
Block a user