Files
myep/docs/travel-snapshot-extended-availability-plan.md
T

3.8 KiB

Travel Snapshot Persistence (DB-Primary + Extended Availability)

Scope

Persist travel payloads in DB and use them as primary local source, with enrichment from BusPro VERFUEGBARKEIT2 (internal naming: extended/ext).

Current Implementation Status

Completed

  • Added snapshot persistence entity and repository:
    • src/Entity/TravelSnapshot.php
    • src/Repository/TravelSnapshotRepository.php
  • Added snapshot application service:
    • src/Service/TravelSnapshotService.php
    • Uses Symfony Serializer JSON payloads for Travel
    • Supports upsert/hash comparison, load, mapping, product lookup, refresh, purge
  • Added extended availability integration:
    • ApiClient::TYPE_AVAILABILITY_EXTENDED = 'VERFUEGBARKEIT2'
    • ApiClient::getAvailabilitiesExtended()
    • parser dispatch in ApiResponseParser
    • ExtendedAvailabilitiesParser
    • models ExtendedAvailability and ExtendedServiceAvailabilityResponse
  • Added DB-primary read path in TravelDataService:
    • tries snapshot first
    • falls back to XML parse + enrichment + snapshot upsert
    • snapshot mapping merged into generateFilesMap()
    • product lookup includes snapshot metadata fallback
  • Added refresh command:
    • app:travel:snapshot-refresh
    • supports batch processing, force mode, optional purge
  • Added migration for snapshot table:
    • migrations/Version20260321120000.php
  • Added serializer type metadata/docblocks in relevant model classes to support stable snapshot deserialization.
  • Removed unified travel cache from TravelDataService::getTravelData():
    • cache and snapshot-version-token logic removed; travel is now loaded directly from snapshot DB (fast indexed lookup) or XML fallback on every call
    • TravelSnapshotService::getCacheVersionToken() removed along with it
  • Fixed hotel-specific lookup correctness:
    • when hotelId is provided, snapshot lookup no longer falls back to another hotel of same date.

Confirmed Behaviors

  • Snapshot data survives XML deletion and remains loadable.
  • Extended refresh updates service-level fields including uhrzeit_von -> Service::timeFrom.
  • Runtime availability overlay (VERFUEGBARKEIT) remains in place.

Design Decisions (Final)

  • Internal naming uses extended/ext; external request type string stays VERFUEGBARKEIT2.
  • DB snapshots are the primary local source for travel loading.
  • Serializer format is JSON via Symfony Serializer, not PHP serialize().
  • No application-level cache wraps getTravelData(); snapshot DB is the fast path, XML is the fallback.

Operational Commands

  • Refresh snapshots:
ddev php bin/console app:travel:snapshot-refresh
  • Force refresh:
ddev php bin/console app:travel:snapshot-refresh --force
  • Force refresh with limit:
ddev php bin/console app:travel:snapshot-refresh --force --limit=500
  • Refresh + purge:
ddev php bin/console app:travel:snapshot-refresh --purge

Open TODOs

  • Revisit DB indexes on travel_snapshot and remove unused ones if desired (date_code, product_id currently appear non-critical for active query paths).
  • Added automated tests:
    • TravelSnapshotServiceTest — upsert, load, exists, generateMapping
    • TravelDataServiceTest — DB-primary + XML fallback paths, insurance rehydration, exception propagation
  • Add/expand automated tests:
    • extended parser coverage
    • snapshot refresh command behavior
  • Define production cron schedule for refresh and cleanup cadence.

Notes

  • If refreshed snapshot data is not visible immediately, ensure the request path is not serving an older in-memory/session DTO. There is no application-level cache on getTravelData(); each call reads the snapshot DB directly, so data is current on the next request after a refresh.