feat: persist travel snapshots and refresh extended availability
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# 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
|
||||
- [x] Added snapshot persistence entity and repository:
|
||||
- `src/Entity/TravelSnapshot.php`
|
||||
- `src/Repository/TravelSnapshotRepository.php`
|
||||
- [x] 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
|
||||
- [x] Added extended availability integration:
|
||||
- `ApiClient::TYPE_AVAILABILITY_EXTENDED = 'VERFUEGBARKEIT2'`
|
||||
- `ApiClient::getAvailabilitiesExtended()`
|
||||
- parser dispatch in `ApiResponseParser`
|
||||
- `ExtendedAvailabilitiesParser`
|
||||
- models `ExtendedAvailability` and `ExtendedServiceAvailabilityResponse`
|
||||
- [x] 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
|
||||
- [x] Added refresh command:
|
||||
- `app:travel:snapshot-refresh`
|
||||
- supports batch processing, force mode, optional purge
|
||||
- [x] Added migration for snapshot table:
|
||||
- `migrations/Version20260321120000.php`
|
||||
- [x] Added serializer type metadata/docblocks in relevant model classes to support stable snapshot deserialization.
|
||||
- [x] 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
|
||||
- [x] Fixed hotel-specific lookup correctness:
|
||||
- when `hotelId` is provided, snapshot lookup no longer falls back to another hotel of same date.
|
||||
|
||||
### Confirmed Behaviors
|
||||
- [x] Snapshot data survives XML deletion and remains loadable.
|
||||
- [x] Extended refresh updates service-level fields including `uhrzeit_von` -> `Service::timeFrom`.
|
||||
- [x] 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:
|
||||
```bash
|
||||
ddev php bin/console app:travel:snapshot-refresh
|
||||
```
|
||||
- Force refresh:
|
||||
```bash
|
||||
ddev php bin/console app:travel:snapshot-refresh --force
|
||||
```
|
||||
- Force refresh with limit:
|
||||
```bash
|
||||
ddev php bin/console app:travel:snapshot-refresh --force --limit=500
|
||||
```
|
||||
- Refresh + purge:
|
||||
```bash
|
||||
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).
|
||||
- [x] 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.
|
||||
Reference in New Issue
Block a user