Skip to content

Conversation

@testower
Copy link
Contributor

@testower testower commented Dec 22, 2025

Summary

Creates a sandbox that processes GBFS geofencing zones at graph build time

Issue

Closes #7120

Unit tests

TBD

Documentation

TBD

Bumping the serialization version id

Yes this needs a new serialization version because we added RentalRestrictionExtension and GeofencingZone to the graph.

@testower testower added +Sandbox This will be implemented as a Sandbox feature +Bump Serialization Id Add this label if you want the serialization id automatically bumped after merging the PR labels Dec 22, 2025
@testower testower force-pushed the poc/sandbox-geofencing-zones-in-graph-builder branch from 312368c to d56b9ba Compare December 22, 2025 14:22
@codecov
Copy link

codecov bot commented Dec 22, 2025

Codecov Report

❌ Patch coverage is 4.69484% with 203 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.97%. Comparing base (729a582) to head (8e5f506).
⚠️ Report is 21 commits behind head on dev-2.x.

Files with missing lines Patch % Lines
...g/internal/graphbuilder/GeofencingZoneApplier.java 0.00% 54 Missing ⚠️
...ernal/graphbuilder/GbfsGeofencingGraphBuilder.java 0.00% 50 Missing ⚠️
...ng/internal/graphbuilder/GeofencingZoneMapper.java 0.00% 41 Missing ⚠️
...fsgeofencing/internal/graphbuilder/GbfsClient.java 0.00% 24 Missing ⚠️
...xt/gbfsgeofencing/config/GbfsGeofencingConfig.java 28.00% 17 Missing and 1 partial ⚠️
...ncing/parameters/GbfsGeofencingFeedParameters.java 0.00% 7 Missing ⚠️
...ng/configure/GbfsGeofencingGraphBuilderModule.java 0.00% 4 Missing ⚠️
...eofencing/parameters/GbfsGeofencingParameters.java 40.00% 2 Missing and 1 partial ⚠️
...rg/opentripplanner/graph_builder/GraphBuilder.java 0.00% 2 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             dev-2.x    #7155      +/-   ##
=============================================
- Coverage      72.12%   71.97%   -0.15%     
- Complexity     21029    21049      +20     
=============================================
  Files           2289     2300      +11     
  Lines          84917    85250     +333     
  Branches        8466     8497      +31     
=============================================
+ Hits           61247    61361     +114     
- Misses         20699    20915     +216     
- Partials        2971     2974       +3     

☔ 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.

@testower testower force-pushed the poc/sandbox-geofencing-zones-in-graph-builder branch 2 times, most recently from 14fadbc to 550c1a9 Compare January 19, 2026 07:22
@testower testower added Entur Test This is currently being tested at Entur and removed Entur Test This is currently being tested at Entur labels Jan 19, 2026
@testower testower force-pushed the poc/sandbox-geofencing-zones-in-graph-builder branch 3 times, most recently from 05cba00 to 0788d82 Compare January 22, 2026 08:24
@vpaturet vpaturet removed the Entur Test This is currently being tested at Entur label Jan 22, 2026
Implement a new sandbox extension that fetches GBFS geofencing zones
during graph build and applies travel restrictions to street edges.

Key components:
- GbfsGeofencingRepository: stores geofencing zones by system ID
- GbfsClient: fetches GBFS v3.0 discovery and geofencing_zones.json
- GeofencingZoneMapper: converts GBFS GeoJSON to OTP GeofencingZone
- GeofencingZoneApplier: applies rental restrictions to street edges
- GbfsGeofencingGraphBuilder: orchestrates the build process

Configuration via build-config.json under gbfsGeofencing with list
of feeds (url, headers, and optional network override).

The zones are serialized with the graph and used at runtime to
restrict vehicle rentals in no-go and slow zones.
Update method-level JavaDoc to explain "why" rather than "what",
following OTP Codestyle.md guidelines. Each method now documents
its purpose, caller context, and role in the system rather than
simply restating the method name.
Handle the case where fetching the GBFS discovery file returns null,
which can happen with network errors or invalid responses. Without
this check, the code would throw an NPE when accessing getData().

Logs a warning to help operators identify misconfigured feed URLs.
The language parameter was declared and documented but never used.
The GBFS geofencing module only supports GBFS v3.0, which has a flat
feed structure with no language dimension (unlike v2.x).

Removing this prevents users from configuring a property that has
no effect.
Phase 1 of thread-safety improvements: Make the repository immutable
after construction instead of using synchronization.

Changes:
- Remove mutable methods from GbfsGeofencingRepository interface
- Make DefaultGbfsGeofencingRepository immutable with constructor-based
  initialization using List.copyOf() for defensive copying
- Add new GbfsGeofencingRepositoryBuilder for use during graph build

This approach ensures thread-safety through immutability rather than
synchronization overhead, matching OTP's pattern for build-time data.
Add null-safety checks for features with missing or empty rules in
the GBFS geofencing zone mapper. The code previously accessed
`getRules().get(0)` directly, which would throw NPE if properties
or rules were null/empty.

Changes:
- Add hasValidRules() predicate method to validate features
- Filter out features with null properties or null/empty rules
- Log warnings for skipped features to aid debugging

This follows the existing defensive coding pattern used in the
featureName() method and the null geometry filter.
Use Map.copyOf() to create an immutable copy of httpHeaders in the
compact constructor, preventing mutation after construction. This
follows the project's immutability guidelines for record types.
Phase 2 of thread-safety implementation for GbfsGeofencingRepository.

Updates the Dagger dependency injection wiring to use the new
GbfsGeofencingRepositoryBuilder instead of the mutable repository:

- GbfsGeofencingRepositoryModule now provides the builder
- GbfsGeofencingGraphBuilderModule injects the builder
- GbfsGeofencingGraphBuilder uses builder to create immutable repository
- GraphBuilderFactory takes builder via @BindsInstance
- LoadApplicationFactory exposes gbfsGeofencingRepositoryBuilder()
- ConstructApplication passes builder to GraphBuilder
- LoadApplication handles both repository (from serialized graph)
  and builder (for fresh builds)

The repository is now built immutably after graph construction
completes, with a getRepository() method to retrieve it.
Add repository caching to GbfsGeofencingRepositoryBuilder and update
ConstructApplication to properly retrieve the repository for both fresh
builds and deserialized graphs.

Key changes:
- GbfsGeofencingRepositoryBuilder now caches the built repository
- Added getBuiltRepository() method for post-build retrieval
- ConstructApplication.gbfsGeofencingRepository() now correctly falls
  back to builder when repository is not available from Dagger

This completes the serialization flow:
- Fresh build: builder creates repository, serialized to graph file
- Graph load: repository deserialized and injected via Dagger
When multiple GBFS providers have business areas, the code incorrectly
used only the first provider's network ID for all business area
boundaries. This caused vehicles from non-first providers to not be
blocked at their own business area boundaries.

The fix groups business areas by network (feed ID) before processing,
then creates a separate BusinessAreaBorder for each network. This
ensures each provider's vehicles are correctly restricted at their
own business area boundaries.
@testower testower force-pushed the poc/sandbox-geofencing-zones-in-graph-builder branch from 0788d82 to 3ef56cb Compare January 23, 2026 06:32
@testower testower added the Entur Test This is currently being tested at Entur label Jan 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

+Bump Serialization Id Add this label if you want the serialization id automatically bumped after merging the PR Entur Test This is currently being tested at Entur +Sandbox This will be implemented as a Sandbox feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Load GBFS Geofencing Zones at Graph Build Time as a Sandbox

2 participants