From 74fd848e9735faa49b51f67ea8e1753a51aeb6be Mon Sep 17 00:00:00 2001 From: Jarkko Kaura Date: Tue, 31 Oct 2023 20:26:26 +0200 Subject: [PATCH] Fix a bug in temporal filtering when importing timetables. Until now, it has been required that the validity period of the exported route must be valid for as long or longer than the Hastus booking record. This causes problems when the exported route is about to expire and a new version already exists, and when the Hastus booking record is valid further into the future than the exported route. Fix the problem by only requiring that the Hastus booking record must start later (or on the same day) as the exported route. Resolves HSLdevcom/jore4#1570 --- .../jore4/hastus/graphql/GraphQLService.kt | 8 +-- .../hastus/service/importing/ImportService.kt | 53 +++++++++++-------- .../graphql/journeypatternrefs.graphql | 9 +--- 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/main/kotlin/fi/hsl/jore4/hastus/graphql/GraphQLService.kt b/src/main/kotlin/fi/hsl/jore4/hastus/graphql/GraphQLService.kt index 08753a56..d093bce7 100644 --- a/src/main/kotlin/fi/hsl/jore4/hastus/graphql/GraphQLService.kt +++ b/src/main/kotlin/fi/hsl/jore4/hastus/graphql/GraphQLService.kt @@ -230,14 +230,14 @@ class GraphQLService( fun getJourneyPatternReferences( routeLabels: Collection, - validityStart: LocalDate, - validityEnd: LocalDate + validityStart: LocalDate ): List { + // It is required that the route referenced by the journey pattern reference must be valid + // before (or at) the start date of the Hastus booking record. val journeyPatternRefsQuery = JourneyPatternRefs( variables = JourneyPatternRefs.Variables( route_labels = routeLabels.toList(), - validity_start = validityStart, - validity_end = validityEnd + validity_start = validityStart ) ) diff --git a/src/main/kotlin/fi/hsl/jore4/hastus/service/importing/ImportService.kt b/src/main/kotlin/fi/hsl/jore4/hastus/service/importing/ImportService.kt index 276e4d7b..91a0f376 100644 --- a/src/main/kotlin/fi/hsl/jore4/hastus/service/importing/ImportService.kt +++ b/src/main/kotlin/fi/hsl/jore4/hastus/service/importing/ImportService.kt @@ -38,8 +38,7 @@ class ImportService(private val graphQLServiceFactory: GraphQLServiceFactory) { val journeyPatternRefs: List = graphQLService.getJourneyPatternReferences( uniqueRouteLabels, - hastusBookingRecord.startDate, - hastusBookingRecord.endDate + hastusBookingRecord.startDate ) LOGGER.debug { "Fetched journey pattern references: $journeyPatternRefs" } @@ -131,28 +130,38 @@ class ImportService(private val graphQLServiceFactory: GraphQLServiceFactory) { throw exception } - val bestJourneyPatternRefMatch: JoreJourneyPatternRef = - journeyPatternRefsMatchedByStopPointLabels - .sortedByDescending { - // TODO Make sure that this is the appropriate ordering criteria when - // finding JourneyPatternRef match. - it.snapshotTime - } - .firstOrNull { journeyPatternRef -> - val joreTimingPlaceLabels: List = - journeyPatternRef.stops.map { it.timingPlaceCode } + val journeyPatternRefsMatchedByTimingPlaceLabels: List = + journeyPatternRefsMatchedByStopPointLabels.filter { journeyPatternRef -> + val joreTimingPlaceLabels: List = + journeyPatternRef.stops.map { it.timingPlaceCode } - joreTimingPlaceLabels == hastusPlaceLabels - } - ?: run { - val exception = CannotFindJourneyPatternRefByTimingPlaceLabelsException( - hastusRouteLabelAndDirection, - hastusStopPointLabels, - hastusPlaceLabels - ) - LOGGER.warn(exception.message) - throw exception + joreTimingPlaceLabels == hastusPlaceLabels + } + + if (journeyPatternRefsMatchedByTimingPlaceLabels.isEmpty()) { + val exception = CannotFindJourneyPatternRefByTimingPlaceLabelsException( + hastusRouteLabelAndDirection, + hastusStopPointLabels, + hastusPlaceLabels + ) + LOGGER.warn(exception.message) + throw exception + } + + val bestJourneyPatternRefMatch: JoreJourneyPatternRef = journeyPatternRefsMatchedByTimingPlaceLabels + .sortedWith( + compareByDescending { + // By choosing the one with the latest validity start date, we are + // effectively choosing the route/journey-pattern that is currently + // active or was most recently active among the candidates. + it.routeValidityStart + }.thenByDescending { + // The last exported item with the most up-to-date route information is + // picked. + it.snapshotTime } + ) + .first() results[hastusRouteLabelAndDirection] = bestJourneyPatternRefMatch } diff --git a/src/main/resources/graphql/journeypatternrefs.graphql b/src/main/resources/graphql/journeypatternrefs.graphql index ceb24738..7c6e9bc4 100644 --- a/src/main/resources/graphql/journeypatternrefs.graphql +++ b/src/main/resources/graphql/journeypatternrefs.graphql @@ -1,7 +1,6 @@ query JourneyPatternRefs( $route_labels: [String!]!, - $validity_start: date!, - $validity_end: date! + $validity_start: date! ) { timetables { timetables_journey_pattern_journey_pattern_ref( @@ -14,12 +13,6 @@ query JourneyPatternRefs( { route_validity_start: { _lte: $validity_start } } ] } - { - _or: [ - { route_validity_end: { _is_null: true } } - { route_validity_end: { _gte: $validity_end } } - ] - } ] } order_by: {