Skip to content

Upstream merge 2026-09-08 - #321

Merged
miles-grant-ibigroup merged 185 commits into
ibi-dev-2.xfrom
upstream-merge-2026-09-08
Sep 10, 2026
Merged

miles-grant-ibigroup merged 185 commits into
ibi-dev-2.xfrom
upstream-merge-2026-09-08

Conversation

@leonardehrenfried

@leonardehrenfried leonardehrenfried commented Sep 8, 2026 •

Copy link
Copy Markdown

There is nothing immediately needed for you guys, but the diff is already enormous, so lets run the smoke test and merge sooner rather than later.

t2gran and others added 30 commits August 15, 2026 01:51
getOrCreateServiceIdForDate mutates serviceIdsByDate's Set values in
place. Any copy of a CalendarServiceData that only shallow-copies that
map still shares those Set instances with the original, so a later
mutation on one side is visible through the other. Add a proper
copyOf() that copies the sets too.
Collapse the TripCalendars interface and its sole DefaultTripCalendars
implementation into a single immutable TripCalendars class. There is no
builder: every modification (merge, withServiceCode, initializeServiceCodes,
getOrCreateServiceIdForDate) returns a new instance rather than mutating this
one, so a caller holding a reference keeps seeing a stable value even while
another reference evolves. A caller that needs a long-lived, continuously
updated view can just hold a plain mutable field and reassign it as each
method returns its result.

getOrCreateServiceIdForDate takes an onUpdate callback rather than returning
the new instance directly, since the common case (a date that's already been
seen) is a pure read that produces no new instance at all — the callback is
only invoked when something actually changed.

The calendar data (service ids and the dates they run on) is stored directly
as plain maps instead of wrapping a CalendarServiceData instance, since that
was only ever used as an internal implementation detail here.
Hold the trip calendar directly as a field on TimetableRepository/
TimetableRepositorySnapshot instead of giving it its own repository handle
and lifecycle. Every consumer that needs realtime timetable data already
needs the calendar too, since new service ids for real-time-added trips must
be visible in the same transaction as the trips that use them, so a separate
handle only added indirection without decoupling anything.

TransitRepository keeps the scheduled-time TripCalendars; DefaultTimetableRepository
owns the realtime write-buffer/snapshot pair, and DefaultTransitService's
getOrCreateServiceIdForDate creates new service ids directly on the write
buffer when write access is available.

Also switch AddTransitEntitiesToTimetable and various test fixtures from
mutating the map returned by TransitRepository.getServiceCodes() directly to
the new TransitRepository.putServiceCode(id, code), since the trip calendar's
service-code map is no longer a bare mutable map exposed for arbitrary external
mutation.

Related to opentripplanner#7893.
…Date to the buffer

getOrCreateServiceIdForDate is a mutation, and TransitService is documented as
a read-only interface used by every read-only call site in the codebase, not
just the 4 real-time updater handlers that actually need to create service
ids. Remove it from TransitService/DefaultTransitService and call it directly
on the mutable TimetableRepository write buffer instead, which all 4 call
sites (NewTripHandler, DuplicatedTripHandler, AddedTripBuilder,
ExtraCallTripBuilder) already have access to, mirroring how they already apply
trip updates directly through the buffer.

The "is this date within the transit service period" check that used to live
in DefaultTransitService (via TransitRepository.transitFeedCovers) moves into
TripCalendars.getOrCreateServiceIdForDate itself, using its own
startDate()/endDate(). Since only in-range dates are ever added and purging
never touches the calendar, that range is stable and self-contained, so the
buffer needs no reference to TransitRepository to enforce it.
UnmodifiableCollectionsSerializer's write/copy path always converted the
wrapped value to an ArrayList via a blind (Collection) cast, and its read/copy
path assumed that deserialized ArrayList was already the concrete type
create() needed. This works for COLLECTION/RANDOM_ACCESS_LIST (a List and a
Collection are compatible enough), but breaks for MAP/SORTED_MAP (a Map is not
a Collection, so the write-side cast throws ClassCastException) and would also
break for SET/SORTED_SET/LIST on the read side (an ArrayList is not a Set, so
that cast would throw too).

Give each variant its own toIntermediate()/create() pair: toIntermediate()
converts to a plain, Kryo-friendly representation appropriate to the type
(ArrayList for collection-based variants, HashMap for map-based ones), and
create() reconstructs the concrete collection/map type it needs from that
representation before wrapping it back up as unmodifiable.

Nothing in the codebase had ever put a plain Collections.unmodifiableMap/Set
into the Kryo-serialized graph before, so this bug was latent until now.
Both are invariant once an instance is built, so compute them once in the
constructor instead of rescanning serviceIdsByDate's whole key set on every
call to startDate()/endDate() — including every call to
getOrCreateServiceIdForDate, which checks both on every invocation.
The method never assigns service codes — it computes
getServiceCodesRunningForDate() from service ids/dates and codes that must
already be registered (it skips any service id without one). The old name
suggested the opposite of what it does.
…KryoSerializedObject

Clarify that the intermediate representation is specifically for Kryo
serialization, and that create() is really the reverse conversion.
…lendar/TripCalendars.java

Co-authored-by: Sigurd Totland <sigurdtotland@gmail.com>
t2gran and others added 26 commits September 4, 2026 11:30
…zation-performance

I will merge this since @vpaturet is not available today - and the only change I made is the same change that Vincent purposed.
…xb-logging

Fix logging of JAXB type names
…update

Update prettier and prettier-java versions
Split graph_builder.module.osm into subpackages
…/logging-dependencies

Update logging dependencies to v2.0.19
…onnectivity

Only add stop connectivity graph build module, when both street and transit exists
…-transport-modes

Add missing carpool transit mode to the Transmodel API mode enum
# Conflicts:
#	application/src/main/java/org/opentripplanner/graph_builder/module/osm/ElevatorProcessor.java
#	application/src/main/java/org/opentripplanner/graph_builder/module/osm/parameters/OsmProcessingParameters.java
…r-ids

Add `elevatorRefTags` build config option to extract elevator ids from OSM
…/guava-monorepo

Update dependency com.google.guava:guava to v33.7.1-jre
…style

Remove UnusedImports checkstyle rule
…/com.google.cloud-libraries-bom-26.x

Update dependency com.google.cloud:libraries-bom to v26.88.0

@miles-grant-ibigroup miles-grant-ibigroup left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Everything is still functioning!

@miles-grant-ibigroup
miles-grant-ibigroup merged commit aebd383 into ibi-dev-2.x Sep 10, 2026
17 checks passed
@miles-grant-ibigroup
miles-grant-ibigroup deleted the upstream-merge-2026-09-08 branch September 10, 2026 13:44
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.

9 participants