Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Timetable immutable #6017

Merged
merged 11 commits into from
Sep 26, 2024

Conversation

vpaturet
Copy link
Contributor

@vpaturet vpaturet commented Aug 23, 2024

Summary

This PR refactors the Timetable class to make it immutable after construction.
The PR introduces a TimetableBuilder.

The builder enforces 2 business rules:

  • trip times must be chronologically sorted in the timetable.
  • a trip can be added only once in a given timetable.

In addition, the TripTimes sorting logic is removed from the TransitLayerMapper, since this is now redundant.

Implementation notes:
Most of the refactoring consists in deferring the creation of the Timetable and TripPattern instances by accumulating changes in their respective builders.
There are 3 notable difficulties:

  1. Since a TripPattern contains a scheduled Timetable that must be created at the same time as the TripPattern itself, the 2 builders (TripPatternBuilder and TimetableBuilder) must be nested.
  2. Updating the Timetables instances in the TimetableSnapshot:
    Implementing copy-on-write in TimetableSnapshot induces some extra work, with entities and collections being repeatedly re-created. When profiling this does not seem to impact performance significantly.
  3. Importing GTFS trips: GenerateTripPatternsOperation:
    GTFS trips are grouped by direction in a given TripPattern. When using a builder, the direction of a Timetable must be evaluated before the Timetable is built, which adds some complexity.

Issue

No

Unit tests

Added unit tests.
Updated unit tests.

Documentation

No

@vpaturet vpaturet added Technical Debt Real-Time Update The issue/PR is related to RealTime updates Skip Changelog labels Aug 23, 2024
@vpaturet vpaturet self-assigned this Aug 23, 2024
vpaturet and others added 6 commits September 13, 2024 10:17
All trip-times in a Timetable should be ordered by the first departure-time for the first
stop in the trip pattern. This was not enforced in the Timetable <-> TimetableBuilder, but
relied on the "outside" to do it. This PR enforces this and provides two methods for adding
trip-times to a Timetable (add & addOrUpdate).
Copy link

codecov bot commented Sep 16, 2024

Codecov Report

Attention: Patch coverage is 93.52941% with 11 lines in your changes missing coverage. Please review.

Project coverage is 69.84%. Comparing base (9c10a0e) to head (e15c3d0).
Report is 22 commits behind head on dev-2.x.

Files with missing lines Patch % Lines
...nner/transit/model/network/TripPatternBuilder.java 71.42% 2 Missing and 2 partials ⚠️
...main/java/org/opentripplanner/model/Timetable.java 81.25% 2 Missing and 1 partial ⚠️
...va/org/opentripplanner/model/TimetableBuilder.java 95.23% 1 Missing and 1 partial ⚠️
...tripplanner/transit/model/network/TripPattern.java 75.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             dev-2.x    #6017      +/-   ##
=============================================
+ Coverage      69.82%   69.84%   +0.02%     
- Complexity     17419    17451      +32     
=============================================
  Files           1974     1975       +1     
  Lines          74545    74600      +55     
  Branches        7633     7634       +1     
=============================================
+ Hits           52048    52106      +58     
+ Misses         19847    19843       -4     
- Partials        2650     2651       +1     

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

@vpaturet
Copy link
Contributor Author

As detailed in #6067, changing the order in which GTFS trips are imported changes the results of the speed test. This is most likely the reason why the speed test fails in this PR: while the order Trips are iterated over is the same, the order in which TripPatterns are built is different.

Investigating and fixing this issue is not in the scope of this PR, but we should at least make sure that test results are stable/reproducible.
This is implemented in the commit 16c8264 by ensuring that TripPatterns are built in the same order that Trips are imported.

@t2gran

@vpaturet vpaturet marked this pull request as ready for review September 16, 2024 13:04
@vpaturet vpaturet requested a review from a team as a code owner September 16, 2024 13:04
@t2gran t2gran added this to the 2.7 (next release) milestone Sep 18, 2024
@leonardehrenfried
Copy link
Member

Thanks for the call where you explained the PR. I will give this a second review once @t2gran's issued have been resolve.

Also, there are merge conflicts.

# Conflicts:
#	src/test/java/org/opentripplanner/transit/service/PatternByServiceDatesFilterTest.java
#	src/test/java/org/opentripplanner/updater/trip/RealtimeTestEnvironment.java
@vpaturet vpaturet merged commit cd5277e into opentripplanner:dev-2.x Sep 26, 2024
5 checks passed
@vpaturet vpaturet deleted the make_timetable_immutable branch September 26, 2024 08:35
@vpaturet
Copy link
Contributor Author

vpaturet commented Oct 8, 2024

Oops, this PR should have been tagged with Bump serialization id.
Not because a class structure has been changed, but because the sorting of trip times is now expected to be done at graph building time.
Any previously built graph stores the serialized TripTimes in an arbitrary order and will fail this precondition:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Real-Time Update The issue/PR is related to RealTime updates Skip Changelog Technical Debt
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants