Skip to content

fix: register missing Situation endpoint route (#798) - #804

Open
tejasva-vardhan wants to merge 3 commits into
OneBusAway:mainfrom
tejasva-vardhan:fix/situation-route-parity
Open

fix: register missing Situation endpoint route (#798)#804
tejasva-vardhan wants to merge 3 commits into
OneBusAway:mainfrom
tejasva-vardhan:fix/situation-route-parity

Conversation

@tejasva-vardhan

@tejasva-vardhan tejasva-vardhan commented Mar 28, 2026

Copy link
Copy Markdown
Contributor

Overview

This PR resolves #798 by properly registering the GET /api/where/situation/{id} route in the REST API. While the handler logic was present, it was not wired to the router, causing a 404/HTML fallback when requesting real-time service alerts.

Changes

  • Route Registration: Registered the missing endpoint in internal/restapi/routes.go.
  • Logic Implementation: Re-implemented the situationHandler to correctly fetch and format service alerts using api.extractAndValidateID.
  • Data Access: Added GetAllAlerts() in internal/gtfs/realtime.go to provide access to the in-memory GTFS-RT alert store.
  • Testing: Added unit tests in internal/restapi/situation_handler_test.go (verified with go test).

Verification (Before vs After)

To ensure full parity with the legacy OBA Java API, I verified the fix using both the maglev-validator and manual browser testing.

1. Maglev Validator Comparison

Local Maglev (localhost:4000) vs Production Java API (api.pugetsound.onebusaway.org).

Stage Comparison Result
Before (Gap) Screenshot 2026-03-29 020453
After (Fixed) Screenshot 2026-03-29 021558

2. Browser Manual Testing

Endpoint: /api/where/situation/1_84714.json?key=test

Stage Response Screenshot
Before (404) Screenshot 2026-03-29 013458
After (200 OK) Screenshot 2026-03-29 021511

Note for Reviewers: - Only core logic files for the fix are included in this PR.

  • Windows-specific driver changes (modernc.org/sqlite) and local performance bypasses were intentionally excluded to maintain upstream standards.

@tejasva-vardhan

Copy link
Copy Markdown
Contributor Author

@aaronbrethorst @Ahmedhossamdev would love any review on this!

@tejasva-vardhan

tejasva-vardhan commented Apr 19, 2026

Copy link
Copy Markdown
Contributor Author

@aaronbrethorst @fletcherw @Ahmedhossamdev @burma-shave would love any review on this!!

@aaronbrethorst

Copy link
Copy Markdown
Member

Code review

Found 2 issues:

  1. The branch is stale and no longer compiles against main — the green checks are from March and were run against an older base. Two symbols this PR depends on have changed since: sort was dropped from internal/gtfs/realtime.go's import block in favor of slices (PR refactor: replace sort package with slices for improved sorting performance #809, "refactor: replace sort package with slices"), so sort.Strings(feedIDs) is now undefined: sort; and Manager.AddTestAlert was renamed to AddAlertForTest (internal/gtfs/gtfs_manager.go:819), so situation_handler_test.go:45 no longer resolves. GitHub still reports the PR as MERGEABLE/CLEAN, so merging as-is would break the build on main. Needs a rebase plus slices.Sort(feedIDs) and AddAlertForTest.

}
sort.Strings(feedIDs)

}
api.GtfsManager.AddTestAlert(alert)

  1. The len(situations) == 0 guard is unreachable. BuildSituationReferences (internal/restapi/reference_utils.go:136) appends unconditionally once per input alert, so a one-element input always yields a one-element result. The 500 path can never be taken and has no test. (CONTRIBUTING.md says "Every new branch or condition introduced by a PR needs test coverage — untested code paths and leftover dead code are common review findings.")

situations := api.BuildSituationReferences([]gtfs.Alert{alert})
if len(situations) == 0 {
api.serverErrorResponse(w, r, fmt.Errorf("unexpected empty situation build for id %q", situationID))
return
}

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@aaronbrethorst aaronbrethorst left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for this, and sorry it sat for so long — that's on us, not you. The endpoint design is right: the handler shape matches our other simple-ID real-time endpoints, extractAndValidateID handles the .json suffix the way the rest of the API does, and putting GetAllAlerts on the manager with dedup-by-ID across feeds under the read lock is the correct place for that logic.

The blocker is that the branch has gone stale, and in a way that GitHub is actively hiding from us. The PR shows as mergeable with green checks, but those checks ran on 2026-03-28 against a main that no longer exists. There's no textual conflict, so nothing flags it — but merging as-is breaks the build in two places:

1. sort is no longer imported in internal/gtfs/realtime.go.

GetAllAlerts calls sort.Strings(feedIDs). Since this branch was opened, #809 ("refactor: replace sort package with slices") removed the sort import from that file — main now uses slices.Sort throughout (three call sites). Because your diff only adds a function body and doesn't touch the import block, the merge result is a file that calls sort.Strings with no sort import: undefined: sort.

Swap it for slices.Sort(feedIDs) to match the surrounding code.

2. AddTestAlert no longer exists.

situation_handler_test.go calls api.GtfsManager.AddTestAlert(alert). On main that helper is named AddAlertForTest (internal/gtfs/gtfs_manager.go:819); AddTestAlert isn't defined anywhere in the repo now. Renaming the call is the whole fix.

A rebase onto main plus those two changes should get CI running against reality again.

Two smaller things while you're in there:

  • The len(situations) == 0 guard in situationHandler is unreachable. BuildSituationReferences appends exactly one Situation per input alert unconditionally, so a one-element input always yields one element. It's dead code and it's the one branch with no test — I'd just drop it.
  • TestSituationHandlerWithSituation builds the alert with Header and Description but only asserts on id, reason, and severity. The translated-string fields are the ones most likely to regress silently; asserting summary and description would make the test earn its keep.

One note that isn't about your code: issue #798 claims the handler and tests already existed and just needed wiring up. That isn't true of main — neither situation_handler.go nor its test exists there, and this PR creates both. So this is a new endpoint implementation, not a one-line route registration. Worth knowing since it means there's no prior art to match, and also worth flagging that we have no spec for this endpoint: it isn't in the maglev wiki, it isn't in testdata/openapi.yml, and the docs repo only describes situation as a referenced element, not a standalone method. I'm comfortable with the envelope you chose, but if you have a reference response from a production OBA server, that'd be good to capture.

Related: references is always empty here, even though a situation's allAffects can carry agency/route/stop/trip IDs that a client would want resolved. Not a blocker given there's no spec to point at, but worth a thought.

Rebase and fix the two build breaks and I'll take another look promptly.

Use slices.Sort and AddAlertForTest so the branch compiles
against current main. Drop the unreachable empty-situation
guard and assert summary and description on the handler test.
@tejasva-vardhan
tejasva-vardhan force-pushed the fix/situation-route-parity branch from c9cfa01 to f20054e Compare August 15, 2026 08:04
@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

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

Next review available in: 12 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

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: f2ca956e-a8c1-4413-9eec-8ffd11c8c15a

📥 Commits

Reviewing files that changed from the base of the PR and between 8554824 and 185369a.

📒 Files selected for processing (4)
  • internal/gtfs/realtime.go
  • internal/restapi/routes.go
  • internal/restapi/situation_handler.go
  • internal/restapi/situation_handler_test.go

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.

@tejasva-vardhan

Copy link
Copy Markdown
Contributor Author

@aaronbrethorst
Rebased onto current main and addressed the review:

  • slices.Sort(feedIDs) in GetAllAlerts
  • AddAlertForTest in the handler test
  • Dropped the unreachable len(situations) == 0 guard
  • Asserted summary and description on the 200 path

Tests share one GTFS manager, and route-handler tests already
seed test-alert-123. GetAllAlerts keeps the first ID, so the
situation test was asserting against the wrong alert.

Co-authored-by: Cursor <cursoragent@cursor.com>
@sonarqubecloud

Copy link
Copy Markdown

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.

[Parity Gap] Orphaned handler: Missing route registration for Situation endpoint (/api/where/situation/{id}.json)

2 participants