Skip to content

Conversation

flaktack
Copy link
Contributor

Summary

Two somewhat related issues are improved relating to realtime stop pattern modifications:

  • a new StopPattern and TripPattern was created if any of headsign, stop id, pickup or alight type were set, even if the value remained the same.
    A check is added that the values are actually modified.
  • old TripPatternForDate values could be used if a trip's stop pattern changed, which could lead to transit planning using an old/invalid version.
    When applying updates RealTimeRaptorTransitDataUpdater removes TripPatternForDates without a corresponding Timetable.

Issue

Unit tests

New tests are added for the improvements.

Documentation

No changes.

This avoids planning trips with old trip patterns leading to invalid
itineraries.
Copy link

codecov bot commented Sep 26, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 72.20%. Comparing base (899aebd) to head (dcc9067).
⚠️ Report is 274 commits behind head on dev-2.x.

Additional details and impacted files
@@              Coverage Diff              @@
##             dev-2.x    #6909      +/-   ##
=============================================
+ Coverage      72.09%   72.20%   +0.10%     
- Complexity     19663    19803     +140     
=============================================
  Files           2123     2151      +28     
  Lines          79432    79972     +540     
  Branches        8050     8058       +8     
=============================================
+ Hits           57270    57744     +474     
- Misses         19321    19392      +71     
+ Partials        2841     2836       -5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@flaktack
Copy link
Contributor Author

This seems to be related to #6197 and #6280

@miklcct
Copy link
Contributor

miklcct commented Sep 29, 2025

This seems to be related to #6197 and #6280

I will check if it fixes #6197 and will report the finding afterwards.

@flaktack flaktack marked this pull request as ready for review October 14, 2025 07:41
@flaktack flaktack requested a review from a team as a code owner October 14, 2025 07:41
Comment on lines 101 to 109
.getTransitService()
.getRealtimeRaptorTransitData()
.getTripPatternsForRunningDate(SERVICE_DATE)
.stream()
.map(TripPatternForDate::getTripPattern)
.map(RoutingTripPattern::getPattern)
.map(AbstractTransitEntity::getId)
.map(Object::toString)
.toList()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is repeated several times. Can you extract a reusable method, perhaps in RealtimeTestEnv?

It will probably heavily collide with #6899 but worth it nonetheless.

Comment on lines 21 to 25
/**
* Tests that stops can be SKIPPED for a trip which repeats times for consecutive stops.
*
* @link <a href="https://github.com/opentripplanner/OpenTripPlanner/issues/6848">issue</a>
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update or remove.

Comment on lines 463 to 484
GtfsRealtime.TripUpdate.Builder tripUpdateBuilder = GtfsRealtime.TripUpdate.newBuilder();
tripUpdateBuilder.setTrip(tripDescriptorBuilder);
tripUpdateBuilder.getTripPropertiesBuilder().setTripHeadsign("foo");
StopTimeUpdate.Builder stopTimeUpdateBuilder = tripUpdateBuilder.addStopTimeUpdateBuilder(0);
stopTimeUpdateBuilder.setStopSequence(1);
stopTimeUpdateBuilder.getArrivalBuilder().setDelay(0);
stopTimeUpdateBuilder.getDepartureBuilder().setDelay(0);
stopTimeUpdateBuilder.getStopTimePropertiesBuilder().setStopHeadsign("foo");
stopTimeUpdateBuilder.getStopTimePropertiesBuilder().setAssignedStopId("A");
stopTimeUpdateBuilder = tripUpdateBuilder.addStopTimeUpdateBuilder(1);
stopTimeUpdateBuilder.setStopSequence(2);
stopTimeUpdateBuilder
.getStopTimePropertiesBuilder()
.setPickupType(StopTimeUpdate.StopTimeProperties.DropOffPickupType.REGULAR);
stopTimeUpdateBuilder
.getStopTimePropertiesBuilder()
.setDropOffType(StopTimeUpdate.StopTimeProperties.DropOffPickupType.REGULAR);
stopTimeUpdateBuilder.setScheduleRelationship(StopTimeUpdate.ScheduleRelationship.SCHEDULED);
stopTimeUpdateBuilder = tripUpdateBuilder.addStopTimeUpdateBuilder(2);
stopTimeUpdateBuilder.setStopSequence(3);
stopTimeUpdateBuilder.getArrivalBuilder().setDelay(0);
stopTimeUpdateBuilder.getDepartureBuilder().setDelay(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that the other tests in this class do the same, but I find the repetition pretty grating.

Can you please make this a little less verbose?

Comment on lines +65 to +72
this.timetableRepository.setRaptorTransitData(
RaptorTransitDataMapper.map(new TestTransitTuningParameters(), timetableRepository)
);
this.timetableRepository.setRealtimeRaptorTransitData(
new RaptorTransitData(timetableRepository.getRaptorTransitData())
);
this.snapshotManager = new TimetableSnapshotManager(
null,
new RealTimeRaptorTransitDataUpdater(timetableRepository),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's great that we are adding test coverage to this critical, yet poorly-understood component.

} else {
LOG.warn("Could not fetch timetable for {}", pattern);
LOG.warn("Could not fetch timetable for {}, removing.", pattern);
patternsForDate.remove(tripPatternForDate);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the most important change in the PR. I absolutely support changing this class but I'm having a hard time understanding the consequences of this change: the code is very complex with several collections updating each other.

If you have a better understanding, do you have time to walk me through the code? Maybe @vpaturet is interested as well.

public void tripNotFoundInPattern() {
// non-existing trip
var tripDescriptorBuilder = tripDescriptorBuilder("b");
var nonExistingTripId = "b";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, thanks for this. I didn't expect you to fix the whole file.

Copy link
Member

@leonardehrenfried leonardehrenfried left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this already in good shape. @vpaturet what do you think of a group review session about RealTimeRaptorTransitDataUpdater?

this.timetableRepository = timetableRepository;
}

public void update(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have the knowledge to do so, can you add some Javadoc to this method?

@habrahamsson-skanetrafiken
Copy link
Contributor

Lets have a group session to look at this after @leonardehrenfried is back from vacation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants