Skip to content

Remove trips consolidation leaves too short - #1777

Draft
aaronbrethorst wants to merge 1 commit into
ab/stop-consolidation-importfrom
ab/stop-consolidation-short-trips
Draft

aaronbrethorst wants to merge 1 commit into
ab/stop-consolidation-importfrom
ab/stop-consolidation-short-trips

Conversation

@aaronbrethorst

@aaronbrethorst aaronbrethorst commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Part of #1977

Draft. Stacked on #1773. Draft until multi-feed phases B and C land.

What it does

When stop consolidation drops a trip's stop times so that it's left with fewer than two, the import removes the trip, as Java does. Removed trips get no stop times, frequencies or block entries.

Root cause

Java's bundle builder drops such trips in two steps:

  1. StopTimeEntriesFactory.processStopTimes discards stop times with no stop. These are the references to an absorbed stop whose canonical stop isn't stored.
  2. TripEntriesFactory.processTrip then returns no trip entry for any trip left with fewer than two stop times ("trip … missing stops!").

Without this change, maglev kept such trips with one stop time, or none. The import guarantees every stored trip has stop times, so a trip with none breaks that.

Testing

  • Test failing on main before this change: n/a. On Add a stop-consolidation-url config option #1773, TestStoreGtfsData_ConsolidatesStops fails without this commit, because trips short and only_dropped survive.
  • Manual check: not run separately. The import test feed below covers each case end to end.
  • The test feed covers:
    • a three-stop trip that keeps two stops (kept)
    • a two-stop trip left with one (removed, together with its frequency)
    • a trip left with none (removed)
    • a one-stop trip whose stop moves (kept: consolidation didn't shorten it)
  • make test, and go vet with both tag sets, pass.

Checklist

  • This PR addresses one issue.
  • It is under ~200 changed lines, or the description says why it can't be split.
  • This PR is not a bug fix, or the new or changed test fails on main and passes on this branch.
  • Each commit is one logical change with a clear message.
  • I did not hand-edit sqlc-generated files under gtfsdb/ (db.go, models.go, query.sql.go) or testdata/openapi.yml (synced from upstream).
  • This PR changes no handler, or handlers pass r.Context() to DB/service calls, not context.Background().
  • The response comparison above is filled in, or this PR doesn't change a Java-served response.
  • This PR adds no endpoint, or each new endpoint matches testdata/openapi.yml, has an issue open on OneBusAway/sdk-config, or is outside the SDK and the description says why.
  • I read every line of this diff and can explain it if asked.

Notes for reviewers

Java drops every trip with fewer than two stop times, not just the ones consolidation shortened. Maglev keeps one-stop trips that come straight from the feed. This PR leaves that alone; matching Java there would change a non-consolidation behavior and deserves its own issue.

@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

The description follows the PR template.

@github-actions

Copy link
Copy Markdown

Performance Smoke Test Results

Status: PASSED

Metric Value
p(95) latency 1.9 ms
Error rate 0.00%
Total requests 339
Req/sec 11.2

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

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

@github-actions

github-actions Bot commented Nov 8, 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 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.

@github-actions

github-actions Bot commented Nov 8, 2026

Copy link
Copy Markdown

Performance Smoke Test Results

Status: PASSED

Metric Value
p(95) latency 1.8 ms
Error rate 0.00%
Total requests 335
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.

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

Reviewed at afc08dd. The removal itself is correct: trips are inserted before stop times, the removed ones never get stop-time rows, and frequencies are filtered before insert, so the only other trips FK holders don't see them. Java's TripEntriesFactory threshold (size() < 2, "missing stops!") matches minStopTimesPerTrip. One stack-ordering suggestion inline.


Generated by Claude Code

Comment thread gtfsdb/stream_import.go
// isTooShortAfterConsolidation reports whether stop consolidation dropped
// enough of a trip's stop times that Java would drop the trip. A trip that
// was already short in the feed is left alone, as maglev always has.
func isTooShortAfterConsolidation(original, consolidated []gtfs.ScheduledStopTime) bool {

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.

#1808 deletes this function two PRs later and replaces it with a plain len(consolidated) < minStopTimesPerTrip, after moving the general "fewer than two stop times" rule into validation. Since that's the end state, it'd be less churn to land #1808's general rule first (it doesn't depend on consolidation, so it could target main on its own) and have this PR use the plain check from the start. That also lets the one-stop-trip behavior change for every feed be reviewed on its own rather than inside a draft consolidation stack.


Generated by Claude Code

@aaronbrethorst

Copy link
Copy Markdown
Member Author

Keeping this in draft until #1808 lands on main as a standalone PR. Once it does, I'll rebase this onto it and swap isTooShortAfterConsolidation for the plain len(consolidated) < minStopTimesPerTrip check.

When stop consolidation drops the stop times of an absorbed stop whose
canonical stop isn't stored, a trip can be left with one stop time or
none. Java's bundle builder drops such a trip: TripEntriesFactory
skips any trip with fewer than two stop times after
StopTimeEntriesFactory has discarded those with no stop.

The import now does the same for trips consolidation shortened. Those
trips are deleted after their stop times stream past, so they get no
stop times, frequencies or block entries. Maglev keeps one-stop trips
that come straight from the feed, as before; Java drops those too, but
that is a separate parity question.
@aaronbrethorst
aaronbrethorst force-pushed the ab/stop-consolidation-short-trips branch from afc08dd to 2580451 Compare November 9, 2026 19:04
@sonarqubecloud

sonarqubecloud Bot commented Nov 9, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Nov 9, 2026

Copy link
Copy Markdown

Performance Smoke Test Results

Status: PASSED

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

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

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

@github-actions

github-actions Bot commented Nov 9, 2026

Copy link
Copy Markdown

Performance Smoke Test Results

Status: PASSED

Metric Value
p(95) latency 2.6 ms
Error rate 0.00%
Total requests 327
Req/sec 10.7

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

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

@aaronbrethorst
aaronbrethorst removed this pull request from stack #1985 November 9, 2026 21:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

follows-template The PR description follows the PR template

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants