Skip to content

feat(ApiWeb): add /transfers endpoint - #1074

Open
thecristen wants to merge 9 commits into
masterfrom
cbj/transfers-endpoint
Open

feat(ApiWeb): add /transfers endpoint#1074
thecristen wants to merge 9 commits into
masterfrom
cbj/transfers-endpoint

Conversation

@thecristen

Copy link
Copy Markdown

Summary of changes

Asana Ticket: Follow up on "🛜 🐞 Daily Schedules sometimes doesn't show school trips " prerequisite

👋🏼 To facilitate displaying in-seat transfers to riders, I embarked on an effort to finally learn V3 API development in order to expose the transfers.txt GTFS data. Please let me know if there are pieces I overlooked or misplaced.

At a high level, this PR:

  • Adds ingestion and parsing of GTFS transfers.txt
  • Adds a controller that lets you query the transfers by trip (to :from_trip_id) and by type (i.e. :transfer_type). Not my prettiest code, most of it is copied from the FacilitiesController but it works ✨
    • Also requires at least one filter to use (e.g. it won't return all the transfers) - this was @lemald 's suggestion and I think it's a good one.
  • Adds a view which shows the attributes, along from_trip, to_trip, from_stop, and to_stop modeled as relationships... open to feedback on that one. I had an earlier draft which showed these as *_id attributes instead, just not sure what the best choice was there.
  • I used 🤖 only to add the unit tests, they looked reasonable to me but please keep me honest on that
  • Finally, the /status endpoint is updated to show last updated timestamp for transfers

I also tried to flesh out the documentation as thoroughly as I could think of, happy to field feedback on that too!

@thecristen
thecristen requested a review from a team as a code owner August 28, 2026 13:53
@thecristen
thecristen requested review from dks-mbta and removed request for a team August 28, 2026 13:53
Comment thread apps/model/lib/model/transfer.ex
Comment on lines +176 to +177
relationship(:from_trip)
relationship(:to_trip)

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.

Thank you for adding transfers to the API 🙌

question(non-blocking): With this PR establishing the relationship from transfer => trips, do you have a sense of if it would be possible to later add a relationship from trip => transfer?

Definitely out of scope for this PR, but I wonder if it is feasible to support a query like /trips/trip_id?include=transfers

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I admittedly don't know how implementing includes works, but I think with the rest of these pieces in place, it'd be a relatively light lift!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I ended up figuring out how to implement it in feat(TripView): include transfers

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.

Amazing!!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Standby while I work on making it ready for prime time - I'm missing a few attributes

image

Comment thread apps/api_web/lib/api_web/views/transfer_view.ex Outdated

def index_data(conn, params) do
case Params.filter_params(params, @filters, conn) do
{:ok, filters} when map_size(filters) > 0 ->

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.

issue: so I worry a bit that by allowing only a filter by type, and allowing the type filter to take a comma-separated list of types, it's still trivially easy to write a query that would return all of the transfers. I'm not sure what to do about it, though, because we've presumably got to allow some filter more general than trip IDs for your use cases on dotcom.

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.

Maybe we could deploy to a dev environment and see what response times are actually like when filtering by multiple types to get a sense of how much of an issue it actually is.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Let's send this to a dev environment! Maybe you can pick which environment/when? Don't want to interfere with anything else that might be going on.

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.

It looks like dev-blue auto-deploys the latest master every night, so you probably want dev-green if you don't want to have to redeploy every day. It doesn't look like anyone else is using dev-green right now.

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.

Re: the volume concern, it looks like our current GTFS (with the just-recently-released Fall rating included) is 13930 entries, so that's the kind of scale we're talking about.

Comment thread apps/api_web/lib/api_web/controllers/transfer_controller.ex
Comment thread apps/parse/lib/parse/transfers.ex Outdated
end

def transfers(%{id: trip_id}, _conn) do
case Transfer.by_from_trip_id(trip_id) do

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.

question: so to confirm, including transfers for a given trip will give you transfers from that trip, and not to it? If so I think I would argue for calling the include argument something else if possible, like from_trip_transfers.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

image

Yeah, I just realized that might've been flawed now that I'm trying to use it... 😩 . Will re-do

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.

3 participants