Skip to content

Fix: includeTrip / includeStatus interaction now matches the specification - #1277

Open
Ahmedhossamdev wants to merge 4 commits into
mainfrom
fix/trip-for-vehicle-status-trip-references
Open

Fix: includeTrip / includeStatus interaction now matches the specification#1277
Ahmedhossamdev wants to merge 4 commits into
mainfrom
fix/trip-for-vehicle-status-trip-references

Conversation

@Ahmedhossamdev

@Ahmedhossamdev Ahmedhossamdev commented Aug 1, 2026

Copy link
Copy Markdown
Member

Fixes: #1276

Description

The trip-for-vehicle endpoint did not follow the specification when includeTrip and includeStatus were used together.

According to Spec Step 4 and Extension 4b:

When the status block is present, the active trip must always be added to data.references. The includeTrip flag only controls whether the trip is included in the response body, meaning it only changes behavior when includeStatus=false.

Maglev only populated references.Trips when includeTrip=true:

  • trip_for_vehicle_handler.go:169
  • trip_details_handler.go:32

To compensate, the endpoint defaulted includeTrip=true, while the specification defines the default as false.

These two incorrect behaviors cancelled each other out with the default request, but diverged as soon as either parameter was explicitly set.

Current behavior

Request:

includeTrip=false&includeStatus=true
Implementation Trips in data.references
Java ✅ 1
Maglev ❌ 0

Java verification

Verified in TripStatusBeanServiceImpl:

  • Whenever a status bean is created, the active trip is added to data.references.
  • This is independent of the includeTripBean flag.

Changes

  • If status != nil, the active trip and its route are added to data.references.
  • The default value of includeTrip is now false, matching the specification.

parseTripParams took its per-endpoint default as a positional bool. A second one would have been unreadable at the call site, so the defaults now travel in a TripParamDefaults struct:

api.parseTripParams(r, TripParamDefaults{IncludeTrip: true, IncludeSchedule: true}, loc)   // trip-details
api.parseTripParams(r, TripParamDefaults{}, loc)                                           // trip-for-vehicle

The new routeReferenceByID helper lives in reference_utils.go and reuses the existing buildRouteModels.

Note: These two changes landed together. Changing the default alone would have removed trip references from the default response.

Resulting behavior

Request Trips in data.references
default (includeStatus=true) ✅ 1
includeTrip=false&includeStatus=true ✅ 1
includeTrip=true&includeStatus=false ✅ 1
includeTrip=false&includeStatus=false ✅ 0

Tests

TestTripForVehicleHandler_IncludeToggles:

  • Inverted the existing includeTrip=false omits trip references test, since that behavior was incorrect.

New TestTripForVehicleHandler_TripReferences covers the three-way interaction:

  • includeTrip=false still yields trip refs via the status path.
  • includeTrip=false&includeStatus=false yields no trip or route references, matching Extension 4a.
  • includeTrip=true&includeStatus=false yields trip refs, which is the only case where the flag matters.

These live in a separate test function rather than as extra subtests: createTestApi sets RateLimit: 5, and six requests against one API instance returns 429.

Unrelated fix included

The first commit removes a MockAddTrip call from setupTestApiWithMockVehicle.

MockAddTrip issues an INSERT OR REPLACE, and the helper passed it the ID of a trip it had just read out of the fixture database — replacing a real trip row with a stub and wiping its block_id, shape_id and service_id. The test database is shared across the package via testDbSetupOnce, so the damage persisted for every test that ran afterwards, and it grew with each caller: the replace moves the row to a new rowid, so the next caller read and clobbered a different trip.

Two callers were enough to break TestGetFirstStopOfNextTripInBlock_WithBlockContinuation, which needs a trip whose block still has a second trip in it. The call was redundant to begin with — the trip already exists in the fixture database, which is where the helper read it from.

It is in this PR only because the new test function cannot pass without it.

Handler consistency

parseTripParams is shared with trip-details, whose spec does default includeTrip to true. That default is preserved and only trip-for-vehicle changes, but the shared helper is worth a second look during review.

Summary by CodeRabbit

  • Bug Fixes
    • Improved trip-for-vehicle responses to include accurate trip and route references when status information is requested.
    • Refined endpoint-specific defaults for trip and schedule details, providing more consistent results across trip-related requests.
    • Improved handling of route lookups and related errors in trip references.
  • Tests
    • Expanded coverage for inclusion parameters, defaults, invalid values, and trip-reference combinations.

setupTestApiWithMockVehicle called MockAddTrip with the ID of a trip it
had just read out of the fixture database. MockAddTrip issues an INSERT
OR REPLACE, so the call replaced a real trip row with a stub, wiping its
block_id, shape_id and service_id.

The test database is shared across the whole package via testDbSetupOnce,
so the damage persisted for every test that ran afterwards, and it grew
with each additional caller of the helper: the replace moves the row to a
new rowid, so the next caller read and clobbered a different trip. Two
callers were enough to break
TestGetFirstStopOfNextTripInBlock_WithBlockContinuation, which needs a
trip whose block still has a second trip in it.

The call was redundant to begin with: the trip already exists in the
fixture database, which is where the helper read it from.
The spec adds the active trip to data.references from the status path, so
it is present whenever the status block is; includeTrip only adds it a
second time and therefore matters solely when includeStatus=false.

Maglev populated references.trips only under includeTrip, and compensated
by defaulting includeTrip to true where the spec defaults it to false. The
two errors cancelled at default settings and diverged as soon as either
flag was set: includeTrip=false&includeStatus=true returned no trip
reference at all, leaving entry.status.activeTripId undereferenceable.

Add the trip and its route to references whenever the status block is
built, and give trip-for-vehicle its documented includeTrip=false default.
parseTripParams took the per-endpoint default as a positional bool; a
second one would have been unreadable at the call site, so the defaults
now travel in a TripParamDefaults struct.
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Ahmedhossamdev, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 788311d3-e954-450b-aacb-9575e21109d2

📥 Commits

Reviewing files that changed from the base of the PR and between b773d99 and aec9257.

📒 Files selected for processing (3)
  • internal/restapi/trip_details_handler.go
  • internal/restapi/trip_for_vehicle_handler.go
  • internal/restapi/trip_for_vehicle_handler_test.go
📝 Walkthrough

Walkthrough

The PR adds separate defaults for trip and schedule inclusion. The trip-for-vehicle handler now adds active trip and route references when status is present, resolves route references with error handling, and expands test coverage for these combinations.

Changes

Trip reference handling

Layer / File(s) Summary
Endpoint-specific trip parameter defaults
internal/restapi/trip_details_handler.go, internal/restapi/trip_details_handler_test.go
parseTripParams now accepts separate includeTrip and includeSchedule defaults. Trip details enables both defaults.
Status-driven trip and route references
internal/restapi/reference_utils.go, internal/restapi/trip_for_vehicle_handler.go
The vehicle handler includes active trip references when status is present. It resolves the trip route through routeReferenceByID and returns lookup errors.
Trip reference and parsing coverage
internal/restapi/trip_for_vehicle_handler_test.go
Tests cover status-dependent references, disabled include parameters, fixture preservation, HTTP success, and the updated defaults type.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant tripForVehicleHandler
  participant parseTripParams
  participant routeReferenceByID
  Client->>tripForVehicleHandler: Send includeTrip and includeStatus
  tripForVehicleHandler->>parseTripParams: Parse endpoint parameters
  tripForVehicleHandler->>routeReferenceByID: Resolve the active trip route
  routeReferenceByID-->>tripForVehicleHandler: Return route reference or error
  tripForVehicleHandler-->>Client: Return trip and route references
Loading

Possibly related PRs

Suggested reviewers: burma-shave

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the fix for the includeTrip and includeStatus interaction in the trip-for-vehicle endpoint.
Linked Issues check ✅ Passed The changes implement the required reference behavior, trip-for-vehicle default, parameter handling, and tests from issue #1276.
Out of Scope Changes check ✅ Passed All changes support issue #1276, including shared parameter parsing, route reference construction, and fixture test corrections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

Performance Smoke Test Results

Status: PASSED

Metric Value
p(95) latency 2.2 ms
Error rate 0.00%
Total requests 333
Req/sec 10.9

Smoke test config: 5 VUs x 30s. Thresholds: p(95) < 300ms, error rate < 1%.

Full results uploaded as workflow artifact: k6-smoke-summary.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/restapi/trip_for_vehicle_handler_test.go (1)

172-187: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the required route-reference contract.

The status-enabled test accepts any non-empty route list. Assert that refs.Trips[0].RouteID exists in refs.Routes.

The all-false and includeStatus=false&includeTrip=false cases assert only that trip references are empty. Assert that route references are also empty.

As per coding guidelines: “Cover every new branch or condition with tests.”

Also applies to: 202-216

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/restapi/trip_for_vehicle_handler_test.go` around lines 172 - 187,
The trip-for-vehicle handler tests need to verify route-reference behavior. In
the status-enabled test, assert that the first trip reference’s RouteID exists
in model.Data.References.Routes; in the all-false and
includeStatus=false/includeTrip=false cases, assert model.Data.References.Routes
is empty alongside the existing trip-reference assertions.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/restapi/trip_details_handler.go`:
- Around line 27-40: Reduce cognitive complexity in RestAPI.parseTripParams by
extracting its date/time parsing and boolean include-parameter parsing branches
into focused helper functions, while keeping endpoint-default initialization in
parseTripParams. Preserve the existing validation, defaults, and returned
TripParams/map behavior.

In `@internal/restapi/trip_for_vehicle_handler.go`:
- Around line 176-179: Correct the comment immediately above the condition in
the trip handler to state that the active trip is appended when IncludeTrip is
requested or when status is present, with IncludeTrip serving as the fallback
when no status block was created; remove the inaccurate claim that it adds a
second reference.
- Around line 192-196: Update the routeReferenceByID error handling in the trip
handler to call sendNotFound when errors.Is(err, sql.ErrNoRows), while retaining
serverErrorResponse for all other errors. Add a handler test covering the
missing-route lookup path and asserting a 404 response.

---

Outside diff comments:
In `@internal/restapi/trip_for_vehicle_handler_test.go`:
- Around line 172-187: The trip-for-vehicle handler tests need to verify
route-reference behavior. In the status-enabled test, assert that the first trip
reference’s RouteID exists in model.Data.References.Routes; in the all-false and
includeStatus=false/includeTrip=false cases, assert model.Data.References.Routes
is empty alongside the existing trip-reference assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b3fad636-d68c-4b45-a552-b43ece104f81

📥 Commits

Reviewing files that changed from the base of the PR and between 3b73fd9 and b773d99.

📒 Files selected for processing (5)
  • internal/restapi/reference_utils.go
  • internal/restapi/trip_details_handler.go
  • internal/restapi/trip_details_handler_test.go
  • internal/restapi/trip_for_vehicle_handler.go
  • internal/restapi/trip_for_vehicle_handler_test.go

Comment thread internal/restapi/trip_details_handler.go
Comment thread internal/restapi/trip_for_vehicle_handler.go Outdated
Comment thread internal/restapi/trip_for_vehicle_handler.go
parseTripParams inlined two near-identical epoch-or-layout timestamp
parses and three near-identical boolean parses, each two levels deep,
which put its cognitive complexity at 43 against an allowed 15.

Pull the repeated shapes into parseEpochOrLayoutTime, parseIncludeParam
and localizeTripTimes, leaving parseTripParams to do endpoint-default
initialization and field-error collection. The accepted formats, the
error messages, the defaults and the returned TripParams are unchanged;
in particular the parsed times are still only re-expressed in the
agency's timezone when the caller supplies one.
The route lookup backing the active trip's reference sent every failure
through serverErrorResponse, so a trip pointing at a route that is not in
the database produced a 500. Elsewhere in this handler, and per the
convention documented in CONTRIBUTING, sql.ErrNoRows is a 404 and only
genuine query failures are 500s.

Also correct the comment above the reference condition: it described the
legacy behaviour of adding the trip twice, whereas this code appends it
once, with includeTrip acting as the fallback when no status block was
built.
@sonarqubecloud

sonarqubecloud Bot commented Aug 1, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

Performance Smoke Test Results

Status: PASSED

Metric Value
p(95) latency 2.1 ms
Error rate 0.00%
Total requests 330
Req/sec 10.9

Smoke test config: 5 VUs x 30s. Thresholds: p(95) < 300ms, error rate < 1%.

Full results uploaded as workflow artifact: k6-smoke-summary.

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.

trip-for-vehicle: add active trip to references from the status path

1 participant