Skip to content

Comments

Verify trip status#462

Open
Ahmedhossamdev wants to merge 96 commits intomainfrom
verify-trip-status
Open

Verify trip status#462
Ahmedhossamdev wants to merge 96 commits intomainfrom
verify-trip-status

Conversation

@Ahmedhossamdev
Copy link
Member

Fix: #108
Replaces: #408

AhmedAlian7 and others added 30 commits February 19, 2026 18:23
- Add database schema for problem_reports_trip and problem_reports_stop
- Implement REST API handlers for submitting problem reports
- Add manual FTS queries to support route_search and stop_search
- Optimize SQL queries to use :exec where appropriate
- Cleanup legacy/unused SQL queries
Replace realtimeService dependency with direct GTFS-RT trip update
consumption for schedule deviation and stop position resolution. Use
service-date-aware time calculations via CalculateSecondsSinceServiceDate.
Remove dead code (block-level position calculation, redundant schedule
deviation methods, pass-through setBlockTripSequence). Propagate request
Replace realtimeService dependency with direct GTFS-RT trip update
consumption for schedule deviation and stop position resolution. Use
service-date-aware time calculations via CalculateSecondsSinceServiceDate.
Remove dead code (block-level position calculation, redundant schedule
deviation methods, pass-through setBlockTripSequence). Propagate request
@Ahmedhossamdev Ahmedhossamdev marked this pull request as ready for review February 23, 2026 23:56
@Ahmedhossamdev
Copy link
Member Author

Hey @aaronbrethorst

I think this branch is ready to be merged now. I suggest we do a squash and merge so our main branch stays linear, since rebasing was too complex to resolve.

Copy link
Member

@aaronbrethorst aaronbrethorst left a comment

Choose a reason for hiding this comment

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

Hey Ahmed, thanks for taking the time to make this substantial improvement to the trip status and vehicle status logic. The overall direction here is excellent: aligning with the Java OBA server's actual semantics for schedule relationships, introducing stale detection, consolidating duplicated code across handlers, and adding thorough test coverage (~1,400 lines of new tests!) are all meaningful wins. The StaleDetector is particularly well-designed, and the bug fixes (timezone time.Local to loc, missing agency prefix on TripID, schedule deviation nanoseconds-to-seconds) are important corrections. Before we can merge this, I will need you to make a couple changes:

Critical

  1. VehicleID no longer includes agency prefix -- behavioral regression. In trips_helper.go:35, the new code sets status.VehicleID = vehicle.ID.ID (e.g., "v123"), but the old code used utils.FormCombinedID(agencyID, vehicle.ID.ID) (e.g., "25_v123"). The OBA API convention uses combined IDs throughout. This is a breaking change for API consumers. Please either restore the combined ID format:

    if vehicle.ID != nil {
        status.VehicleID = utils.FormCombinedID(agencyID, vehicle.ID.ID)
    }

    or, if the raw ID is intentional (to match vehicles_for_agency_handler.go), document it as a deliberate change.

  2. fillStopsFromSchedule can overwrite vehicle-derived ClosestStop. In trips_helper.go:117-119, the guard is:

    if status.ClosestStop == "" || status.NextStop == "" {
        api.fillStopsFromSchedule(...)
    }

    But inside fillStopsFromSchedule, both ClosestStop and NextStop are unconditionally set. If the vehicle-based stop-finding successfully set ClosestStop but not NextStop (e.g., vehicle is at the last stop of a trip), the more accurate vehicle-derived value gets overwritten with a schedule-based guess. Please guard the individual fields:

    if i > 0 && status.ClosestStop == "" {
        status.ClosestStop = ...
    }
    if status.NextStop == "" {
        status.NextStop = ...
    }
  3. BuildTripStatus uses mismatched trip IDs for stop times vs shape queries. GetStopTimesForTrip on line 63 uses activeTripRawID (which may differ from the requested trip if the vehicle was reassigned within a block), but GetShapePointsByTripID on line 121 uses the original tripID. If the vehicle is on a different trip within the block, the shape data and stop times will be for different trips, producing incorrect position/distance calculations. Please use a consistent trip ID for both, and add a comment explaining the choice.

Important

  1. Missing RLock comment on BuildTripStatus. The main branch has // IMPORTANT: Caller must hold manager.RLock() before calling this method. above this function, but the PR dropped it. Since BuildTripStatus calls GetSituationIDsForTrip (which documents the same requirement), please restore the comment.

  2. MockAddVehicle and MockAddVehicleWithOptions don't acquire realTimeMutex. The new MockAddTripUpdate and MockResetRealTimeData both correctly lock m.realTimeMutex, but the vehicle mock methods don't. This inconsistency could cause flaky tests. Please add locking to be consistent.

  3. getFirstStopOfNextTripInBlock silently swallows three database errors. This new function (trips_helper.go:951-982) returns nil for GetTrip, GetTripsByBlockIDOrdered, and GetStopTimesForTrip failures with zero logging. Please add slog.Warn logging consistent with the pattern used in calculateBlockTripSequence right above it.

  4. Inconsistent error handling for BuildTripSchedule failure. In trip_details_handler.go:151, a BuildTripSchedule failure returns a server error response. In trip_for_vehicle_handler.go:102, the same failure is logged as a warning and the handler continues with nil schedule. These should behave consistently -- either both should degrade gracefully or both should return a server error.

  5. Missing test coverage for negative schedule deviation (early vehicles). Every test uses positive deviation (late vehicle). The effectiveScheduleTime calculation in findStopsByScheduleDeviation flips sign for negative deviations, which could produce unexpected results. Please add at least one test with a negative deviation.

  6. Missing test for getFirstStopOfNextTripInBlock success path. TestFindNextStopBySequence_StoppedAtLastStop only exercises the failure case (trip not in DB). There's no test verifying that the block continuation logic correctly finds the first stop of the next trip in a block. This is a critical real-world scenario.

  7. findNextStopBySequence has a redundant serviceDateForBlock parameter. The function signature has both serviceDate time.Time and serviceDateForBlock time.Time, but the call site always passes the same value for both. If they're always identical, simplify the signature to avoid confusion.

Fit and Finish

  1. Missing doc comments on exported functions. GetScheduleDeviation and GetStopDelaysFromTripUpdates in trip_updates_helper.go are exported but have no doc comments. Please add brief comments explaining what they return (seconds, priority of trip-level vs stop-level delay, etc.).

  2. scheduleRelationshipStatus silently maps UNSCHEDULED, REPLACEMENT, and DELETED to "SCHEDULED". While this matches the Java behavior, a DELETED trip being reported as "SCHEDULED" is semantically concerning. Please add a comment to the default case noting the intentional omission.

  3. Comment in BuildVehicleStatus claims avoiding a duplicate query, but getVehicleDistanceAlongShapeContextual makes its own GetShapePointsByTripID call. The comment on vehicles_helper.go:128 ("avoiding a duplicate GetShapePointsByTripID query") is inaccurate. Please either fix the comment or refactor to actually avoid the duplicate query.

  4. OPTIONAL: Java line number references are fragile. Comments referencing specific line numbers in Java source files (e.g., "line 252-253") will drift as the Java codebase evolves. Consider referencing method names only (e.g., TripStatusBeanServiceImpl.getBlockLocationAsStatusBean()).

  5. shapeRowsToPoints drops ShapeDistTraveled without documenting it. The conversion intentionally discards distance data from the database rows. Please note this in the comment so future developers understand distances are recomputed via preCalculateCumulativeDistances.

  6. Empty phase for canceled trips should be documented. GetVehicleStatusAndPhase returns "" for phase when the trip is canceled. Add a brief comment explaining this matches Java's null-phase behavior for canceled trips.

Thanks again, and I look forward to merging this change.

@Ahmedhossamdev
Copy link
Member Author

Ahmedhossamdev commented Feb 25, 2026

BuildTripStatus uses mismatched trip IDs for stop times vs shape queries. GetStopTimesForTrip on line 63 uses activeTripRawID (which may differ from the requested trip if the vehicle was reassigned within a block), but GetShapePointsByTripID on line 121 uses the original tripID. If the vehicle is on a different trip within the block, the shape data and stop times will be for different trips, producing incorrect position/distance calculations. Please use a consistent trip ID for both, and add a comment explaining the choice.

For this I think for this we should use the activeTripId because it's changing based of the GTFS-RT data.

@Ahmedhossamdev
Copy link
Member Author

@aaronbrethorst Done

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.

Verification & Testing Checklist for trip-details and trip-status element

3 participants