Skip to content

Reuse resolved situations for arrivals - #1347

Merged
aaronbrethorst merged 1 commit into
OneBusAway:mainfrom
soumajitgh:agent/reuse-arrival-situations
Aug 19, 2026
Merged

Reuse resolved situations for arrivals#1347
aaronbrethorst merged 1 commit into
OneBusAway:mainfrom
soumajitgh:agent/reuse-arrival-situations

Conversation

@soumajitgh

@soumajitgh soumajitgh commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Reuse situation references resolved by BuildTripStatus for each plural arrival.
  • Add regression coverage for route-level alerts and situation-reference resolution.

Why

The arrivals-and-departures handler resolved each trip’s alerts twice per arrival row. Reusing the existing references removes that repeated work and keeps entry IDs aligned with references.situations.

Validation

  • go vet -tags "sqlite_fts5 sqlite_math_functions" ./...
  • go vet -tags "purego" ./...
  • make test

Closes #1341

Summary by CodeRabbit

Summary by CodeRabbit

  • Bug Fixes
    • Route-level service alerts now appear correctly on affected arrival and departure results.
    • Alert situation references are now consistently included with the associated stop information.
    • Resolved situations are handled consistently when displaying alerts for individual arrivals and departures.

@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3ea09825-d3b2-49cd-a0a0-61d53e14344c

📥 Commits

Reviewing files that changed from the base of the PR and between d9d5baa and a73efdf.

📒 Files selected for processing (1)
  • internal/restapi/arrivals_and_departures_for_stop_handler_test.go

Included review availability: Your plan includes up to 1 review per rolling hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The arrivals handler reuses situations resolved by BuildTripStatus. A new end-to-end test verifies route-level alert IDs on arrivals and in references.situations.

Changes

Arrival situation references

Layer / File(s) Summary
Resolved situations and reference validation
internal/restapi/arrivals_and_departures_for_stop_handler.go, internal/restapi/arrivals_and_departures_for_stop_handler_test.go
The handler adds BuildTripStatus situations to the shared collector and derives arrival situation IDs from them. The test verifies route-alert references in the affected arrival and response references.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to a73ef

This is a small localized change that reuses resolved situation references for arrivals and adds regression coverage; no actionable merge-blocking risk remains beyond normal checks and review.

Possibly related PRs

  • OneBusAway/maglev#1000 — Changes BuildTripStatus and the arrivals handler’s status flow used by this update.
  • OneBusAway/maglev#1313 — Introduces the trip situation and shared collector changes reused here.
  • OneBusAway/maglev#1314 — Refactors situation references in the arrivals/departures handler extended by this update.

Suggested reviewers: burma-shave, aaronbrethorst

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: reusing resolved situations for arrivals.
Linked Issues check ✅ Passed The implementation reuses BuildTripStatus situations, removes duplicate alert resolution, and adds the required route-alert reference test for issue #1341.
Out of Scope Changes check ✅ Passed All changes support issue #1341 by updating arrival situation handling and adding focused regression coverage.

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.

@ARCoder181105 ARCoder181105 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Traced both paths — the refactor is output-identical, and the perf win is real.

GetAlertsForTrip and situationRefsForTrip both do GetTripGetRouteGetAlertsByIDs(tripID, routeID, agencyID) and both end at situationRefsFromAlerts(alerts, agencyID). Same alerts, same IDs — so this drops one duplicated GetTrip+GetRoute+alert-index scan per arrival row, which matters on wide minutesBefore/minutesAfter windows. It also makes the plural handler match the singular one (arrival_and_departure_for_stop_handler.go:401).

One request, two notes.

1. arrivals_and_departures_for_stop_handler_test.go:135 — the test passes on the pre-change code too.

Revert the one-line change and it still goes green, because the old path resolved the same alert with the same ID. Good coverage of the situationIds↔references invariant, but it doesn't pin what this PR changed. Asserting the IDs came from the status would, replacing line 135:

	require.NotNil(t, affectedArrival.TripStatus)
	assert.Equal(t, affectedArrival.TripStatus.SituationIDs, affectedArrival.SituationIDs,
		"arrival situationIds must be the ones BuildTripStatus resolved, not a second lookup")
	assert.Contains(t, affectedArrival.SituationIDs, wantSituationID,

That's exactly the property the commit claims, and it breaks if someone reintroduces a separate lookup.

2. arrivals_and_departures_for_stop_handler.go:448 — consistency nit only, fine to leave.

statusExtras.snapshot is read inside if status != nil (line 393) while statusExtras.situations is read outside it, so the two reads of the same struct look like they have different safety requirements. Both guards are in fact unreachable — every return in BuildTripStatus (trips_helper.go:103, 108, 366) passes a non-nil status and a non-nil extras. No change needed.

Correcting my earlier version of this point: I suggested api.tripSituationsFor(ctx, st.TripID, statusExtras) here. That was wrong — it returns ([]string, []models.Situation) and bypasses the situationCollector, which this handler needs so dedupe stays in one place and references.Situations is built once at line 624. Using it would mean hand-appending and hand-deduping per arrival. A nil guard would also be dead code, and risks leaving situationIDs nil, which marshals as "situationIds": null instead of []; the current addRefs avoids that via make([]string, 0, len(refs)). The code as written is correct.

3. Commit message body has literal \n instead of newlines — renders as one unwrapped line. Worth an amend while it's a single commit.

Verified against the deployed Puget Sound server: stop 1_10190 (Route 70 reroute) returns 1_86736 on each affected arrival with a matching references.situations entry — the shape this PR preserves. Two notes from that, both out of scope here:

  • Alert IDs arrive already prefixed (1_86736), so the idempotency guard in situationID() is load-bearing.
  • Prod returns entry.situationIds: [] at the top level on that stop, while we emit the union of every collected ref. Pre-existing, but this PR now feeds that union from a new source, so it may be worth a separate look.

Comment thread internal/restapi/arrivals_and_departures_for_stop_handler_test.go
@ARCoder181105

Copy link
Copy Markdown
Collaborator

@soumajitgh can you rebase and squash the PR into single atomic commit , as the commit history still consist the anomaly of \n we have to remove that..

Avoid resolving alerts a second time for every arrival row.

Keep arrival situation IDs tied to the references resolved by BuildTripStatus.

Refs OneBusAway#1341
@soumajitgh
soumajitgh force-pushed the agent/reuse-arrival-situations branch from a73efdf to 1e213ca Compare August 17, 2026 10:04
@sonarqubecloud

Copy link
Copy Markdown

@soumajitgh

soumajitgh commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

@ARCoder181105 done

@ARCoder181105 ARCoder181105 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@aaronbrethorst

Copy link
Copy Markdown
Member

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

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

Four lines of production code for a real win on an endpoint where
minutesBefore/minutesAfter can each be 24 hours. Good trade.

I didn't take the equivalence on faith — I traced both sides.
GetAlertsForTrip (internal/gtfs/realtime.go:154) and situationRefsForTrip
(internal/restapi/trips_helper.go:833) do the same resolution: GetTrip
GetRouteGetAlertsByIDs(tripID, routeID, agencyID), both feeding
situationRefsFromAlerts with the same agency. So the reused set is
trip+route+agency scoped exactly as before, addRefs allocates a fresh slice
per call and dedupes on the same key, and references.situations composition is
unchanged. Worth noting for the record: issue #1341's premise that
GetAlertsForTrip "matches on trip alone" is stale — the two sets were already
identical, so this is a pure performance refactor rather than a behavior fix.
That's a better outcome, not a worse one, but it's worth being precise about.

Also a nice side effect: the line you removed was the handler's only r.Context()
use, which bypassed the snapshot-cache-wrapped ctx established earlier in the
function. Everything now flows through the right context.

Two notes, neither blocking:

  • The new test is a good invariant guard (situationIds ↔ references.situations),
    but it doesn't actually pin this change — since both paths resolve the same
    set, it passes on pre-change code too. @ARCoder181105 made this point on the
    earlier revision and it still stands; the test is worth keeping, just not for
    the reason the description gives.
  • This PR removes the last production caller of
    Manager.GetAlertsForTrip — after it lands, only realtime_test.go exercises
    it. CONTRIBUTING.md calls out leftover dead code specifically. I'd rather not
    grow a 4-line perf PR to cover it, but a quick follow-up deleting that method
    and its test would be welcome if you want to take it.

Merging.

@aaronbrethorst
aaronbrethorst merged commit 710c211 into OneBusAway:main Aug 19, 2026
9 checks passed
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.

arrivals-and-departures re-resolves each trip's alerts per arrival row

3 participants