Skip to content

return stoptimesForDate from the schedule if it is called with no parameter on a day when the trip does not run #6480

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 18 commits into from

Conversation

tkalvas
Copy link
Contributor

@tkalvas tkalvas commented Feb 21, 2025

Fixes Issue #6475

Technically the solution here is wrong, but longstanding UIs (like digitransit-ui) rely on getting the scheduled timetable when running stoptimesForDate without a parameter on a wrong day.

Copy link

codecov bot commented Feb 21, 2025

Codecov Report

Attention: Patch coverage is 71.42857% with 4 lines in your changes missing coverage. Please review.

Project coverage is 70.18%. Comparing base (04fadbf) to head (fd6c9bb).
Report is 223 commits behind head on dev-2.x.

Files with missing lines Patch % Lines
...ipplanner/apis/gtfs/datafetchers/StoptimeImpl.java 33.33% 2 Missing ⚠️
...entripplanner/apis/gtfs/datafetchers/TripImpl.java 50.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             dev-2.x    #6480      +/-   ##
=============================================
- Coverage      70.20%   70.18%   -0.03%     
- Complexity     18313    18317       +4     
=============================================
  Files           2080     2082       +2     
  Lines          77182    77220      +38     
  Branches        7831     7833       +2     
=============================================
+ Hits           54183    54193      +10     
- Misses         20230    20259      +29     
+ Partials        2769     2768       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@optionsome optionsome added Regression This feature is no longer working. Digitransit Test Feature is under testing in Digitransit environment(s) labels Feb 27, 2025
…es even if the trip does not run today. Technically wrong, but UIs rely on this, and have for a long time
@tkalvas tkalvas marked this pull request as ready for review March 4, 2025 09:00
@tkalvas tkalvas marked this pull request as draft March 4, 2025 09:35
@tkalvas tkalvas marked this pull request as ready for review March 4, 2025 10:45
@tkalvas tkalvas changed the title return stoptimesForDate even if the trip does not run on the date it is queried return stoptimesForDate from the schedule if it is called with no parameter on a day when the trip does not run Mar 4, 2025
@optionsome optionsome self-requested a review March 6, 2025 10:52
public Optional<List<TripTimeOnDate>> getTripTimeOnDates(
Trip trip,
LocalDate serviceDate,
boolean useScheduledWhenNonRunning
Copy link
Member

Choose a reason for hiding this comment

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

The name of this parameter is a bit confusing as my first intuition at least is that it would use scheduled times from the given date instead of trying to use real-time when trip is cancelled, or something like that. Maybe something like fallbackToNextScheduledDate instead.

Copy link
Member

Choose a reason for hiding this comment

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

I think we usually use the word "schedule" for the describing the "planned data". We had this discussion last year at some point but I can't quite remember what we decided. However, in this case I think "scheduled date" doesn't indicate as strongly that we would be using planned data so I think we could improve the name. Problem with fallbackToBaseTimetable is that it doesn't tell that the returned times could actually be from another service date.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fallbackToBaseTimetableOnRunningDate?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I know Joel will say that doesn't indicate which date, but the fact is that it does not matter which date it is, because it's not really any date. It's just the base case, unchanged by realtime data. The returned result will not include dates, if you try to fetch one it will be null.

Copy link
Member

Choose a reason for hiding this comment

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

I think we use "running date" sometimes to call the actual date that the trip is servicing on. So for example, if a trip lasts 3 days, it's running on 3+ running dates. So this could be slightly confusing as it could confuse people into thinking that the serviceDate parameter could be used as a running date if there is no service on the service date. Maybe fallbackToNextPlannedTimetable? I think the words we use for the planned data are either scheduled or planned.

Copy link
Contributor

Choose a reason for hiding this comment

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

fallbackToPlannedTimetableOnNonRunningDate ?

Copy link
Member

Choose a reason for hiding this comment

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

As said, I think we should avoid using the word running date here because it can mean slightly different thing. Also, I first thought you mean timetable on non running date, but I guess you mean you fall back to planned timetable when there is no service on the service date? I know that the "next" I used in my suggestion is not really that relevant, it could be any date that the trip is servicing on, but I wanted to somehow tell that the timetables don't necessarily come from the given service date.

Copy link
Contributor

@miklcct miklcct Mar 7, 2025

Choose a reason for hiding this comment

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

Yes, we want to specify that "we fall back to the planned timetable when the service does not run on the given service date".

How about fallbackToPlannedTimetableOnNoServiceDate?

Copy link
Member

Choose a reason for hiding this comment

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

That's ok for me.

Comment on lines 77 to 79
* @return if the trip doesn't run on the date specified, return schedule if
* useScheduledWhenNonRunning is true, empty otherwise. Logically this is confusing,
* but existing UIs depend on this.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* @return if the trip doesn't run on the date specified, return schedule if
* useScheduledWhenNonRunning is true, empty otherwise. Logically this is confusing,
* but existing UIs depend on this.
* @return if the trip doesn't run on the specified service date, return trip times from
* the next scheduled service date if fallbackToNextScheduledDate is true, empty
* otherwise. Logically this is confusing, but existing API users depend on this.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the description above is not accurate as well. There is a possibility that the next scheduled service date has been modified by the real-time updates. For example, today is 2025-03-06 when the trip does not run, and the service on 2025-03-07 has been replaced. This method won't return the replaced service, but instead the original scheduled times without real-time updates.

Copy link
Member

Choose a reason for hiding this comment

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

Yep, I think we could add a sentence describing that real-time data is only used for the current date.

@tkalvas tkalvas requested a review from optionsome March 6, 2025 13:26
Comment on lines 77 to 79
* @return if the trip doesn't run on the date specified, return schedule if
* useScheduledWhenNonRunning is true, empty otherwise. Logically this is confusing,
* but existing UIs depend on this.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the description above is not accurate as well. There is a possibility that the next scheduled service date has been modified by the real-time updates. For example, today is 2025-03-06 when the trip does not run, and the service on 2025-03-07 has been replaced. This method won't return the replaced service, but instead the original scheduled times without real-time updates.

new TripTimeOnDate(REALTIME_TRIP_TIMES, 1, REAL_TIME_PATTERN, SERVICE_DATE, midnight)
)
),
service.getTripTimeOnDates(TRIP, SERVICE_DATE, true)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you are testing for a wrong date. SERVICE_DATE is a date the service does run, and NO_SERVICE_DATE is a date the service does not run.

@tkalvas tkalvas requested a review from miklcct March 7, 2025 09:55
@miklcct
Copy link
Contributor

miklcct commented Mar 7, 2025

My only concern left is the name of the boolean parameter. I have merged this PR into our test deployment which will be deployed over the weekend, and I will check if it works early next week (especially regarding to added trips).

@tkalvas tkalvas requested a review from miklcct March 7, 2025 12:08
public Optional<List<TripTimeOnDate>> getTripTimeOnDates(
Trip trip,
LocalDate serviceDate,
boolean fallbackToPlannedTimetableOnNonRunningDate
Copy link
Member

Choose a reason for hiding this comment

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

The latest suggestion for the name is fallbackToPlannedTimetableOnNoServiceDate.

Optional<List<TripTimeOnDate>> getTripTimeOnDates(
Trip trip,
LocalDate serviceDate,
boolean fallbackToPlannedTimetableOnNonRunningDate
Copy link
Member

Choose a reason for hiding this comment

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

fallbackToPlannedTimetableOnNoServiceDate

Comment on lines 76 to 81
/**
* @return if the trip doesn't run on the specified service date, return scheduled trip times,
* unmodified by any realtime data, if
* fallbackToNextScheduledDate is true, empty otherwise. Logically this is confusing, but
* existing API users depend on this.
*/
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/**
* @return if the trip doesn't run on the specified service date, return scheduled trip times,
* unmodified by any realtime data, if
* fallbackToNextScheduledDate is true, empty otherwise. Logically this is confusing, but
* existing API users depend on this.
*/
/**
* @return if the trip doesn't run on the specified service date, return scheduled trip times,
* unmodified by any realtime data, if fallbackToPlannedTimetableOnNoServiceDate is true,
* empty otherwise. Logically this is confusing, but existing API users depend on this.
*/

@tkalvas tkalvas requested a review from optionsome March 10, 2025 07:38
@optionsome
Copy link
Member

@miklcct in #6245 you did some changes to trip's arrivalStoptime, departureStoptime, stoptimes and stoptimesForDate. Were there any functional changes to arrivalStoptime, departureStoptime or stoptimes? Also, was it required to change the behaviour of stoptimesForDate (when you provide the date as a parameter) to get some feature of yours to work or did you just want to fix the bug of it returning times for other days?

I have thought a bit more about how people might have used the stoptimesForDate even with the serviceDate parameter and unfortunately I think we might need to revert changes to it since I think some software might rely on the old "broken" logic. I think we should deprecate stoptimesForDate field on trip and replace it with one or two new fields that do this type of validation that you wanted to add and perhaps are a better fit for some use cases where people want to fetch real-time stop times for multiple days.

@miklcct
Copy link
Contributor

miklcct commented Mar 10, 2025

@miklcct in #6245 you did some changes to trip's arrivalStoptime, departureStoptime, stoptimes and stoptimesForDate. Were there any functional changes to arrivalStoptime, departureStoptime or stoptimes? Also, was it required to change the behaviour of stoptimesForDate (when you provide the date as a parameter) to get some feature of yours to work or did you just want to fix the bug of it returning times for other days?

I have thought a bit more about how people might have used the stoptimesForDate even with the serviceDate parameter and unfortunately I think we might need to revert changes to it since I think some software might rely on the old "broken" logic. I think we should deprecate stoptimesForDate field on trip and replace it with one or two new fields that do this type of validation that you wanted to add and perhaps are a better fit for some use cases where people want to fetch real-time stop times for multiple days.

I am using stoptimesForDate field to fetch real-time stop times for yesterday, today and tomorrow as a workaround for the inability to query the times for the whole trip from a stoptimes, so I have to match the service dates and pick the correct one, and I plan to use this same field in another page where the user can query the timetable for the same trip on an arbitrary date as well.

For arrivalStopTime and departureStopTime, if the date is not specified, the scheduled time is used so there are no functional changes for these two fields, and stoptimes do not accept a date parameter so no functional change is done on that, and it always return the scheduled times.

In the long run I plan to deprecate the whole class of Stoptime and replace them with undated and dated classes.

Btw, what is the issue caused on Digitransit by my change? Can you please explain how Digitransit uses the information from stoptimesForDate without a parameter, on a date when the service does not run?

@miklcct
Copy link
Contributor

miklcct commented Mar 10, 2025

Btw I think that there is also a possible bug in the digitransit-ui after I do a Github search on the use of stoptimesForDate without a date parameter that was the very reason I had to make a workaround to get the stop times in my journey plans.

This bug should happen if you get an itinerary which involves taking service across two service days (such as an overnight trip), or plan a future itinerary, in this case you will be fetching the stoptimes for today even though that the itinerary is for tomorrow, so at worst the complete wrong times will be shown and mislead the user, in case the trip today is heavily delayed (where the user will think that the trip tomorrow is delayed) or even replaced completely with a REPLACEMENT trip.

https://github.com/HSLdevcom/digitransit-ui/blob/917ccb4917a6c320f1aedcc920a45efd087f154d/app/component/itinerary/ItineraryDetails.js#L667

https://github.com/HSLdevcom/digitransit-ui/blob/917ccb4917a6c320f1aedcc920a45efd087f154d/app/component/itinerary/PlanConnection.js#L146

May I kindly suggest that everyone affected by this change check your intention of your GraphQL queries that you are showing the stop times of the correct date to the user, thanks, or if you ALWAYS intend to show the scheduled times (not even today's delays) if stoptimesForDate is called with no parameters.

@optionsome
Copy link
Member

what is the issue caused on Digitransit by my change? Can you please explain how Digitransit uses the information from stoptimesForDate without a parameter, on a date when the service does not run?

The first problem we spotted was when you did a itinerary search for the future and opened some itinerary suggestion because it was using stoptimesForDate without serviceDate parameter.

May I kindly suggest that everyone affected by this change check your intention of your GraphQL queries that you are showing the stop times of the correct date to the user, thanks, or if you ALWAYS intend to show the scheduled times (not even today's delays) if stoptimesForDate is called with no parameters.

Yep, we plan to go through our usage of the stoptimesForDate field to see if it is used properly. However, the problem is that there hundreds of API users and it's difficult to have them all change their software to match the new implementation. Therefore, I think we will look into added new fields to the trip to replace the old stoptimes fields. Perhaps we can discuss this a bit tomorrow either in the normal dev meeting or in the design meeting?

@miklcct
Copy link
Contributor

miklcct commented Mar 10, 2025

what is the issue caused on Digitransit by my change? Can you please explain how Digitransit uses the information from stoptimesForDate without a parameter, on a date when the service does not run?

The first problem we spotted was when you did a itinerary search for the future and opened some itinerary suggestion because it was using stoptimesForDate without serviceDate parameter.

In such case, it is highly likely that you are showing the wrong delays if the same trip on today is delayed. Try to plan a journey for the future on a route which has a severe delay today.

May I kindly suggest that everyone affected by this change check your intention of your GraphQL queries that you are showing the stop times of the correct date to the user, thanks, or if you ALWAYS intend to show the scheduled times (not even today's delays) if stoptimesForDate is called with no parameters.

Yep, we plan to go through our usage of the stoptimesForDate field to see if it is used properly. However, the problem is that there hundreds of API users and it's difficult to have them all change their software to match the new implementation. Therefore, I think we will look into added new fields to the trip to replace the old stoptimes fields. Perhaps we can discuss this a bit tomorrow either in the normal dev meeting or in the design meeting?

I can discuss this in a design meeting as I have intention to deprecate serviceDay field in Stoptime type, or even all date-dependent fields in Trip type in the future (and use TripOnServiceDate) for such purpose.

@t2gran t2gran added this to the 2.8 (next release) milestone Mar 12, 2025
@miklcct
Copy link
Contributor

miklcct commented Mar 13, 2025

After the developer meeting, we have discussed that we will revert to the old behavior (return the planned schedule regardless if the service actually run) since we are not supposed to introduce breaking changes into the API, and leave a documentation for this strange behavior and a workaround for the intended behavior using Trip.activeDates.

In the long term, we will deprecate this field, and all date-dependent fields in Trip, and move all such similar usages to TripOnServiceDate instead.

P.S. unfortunately the change has already been released in the 2.7 version into the wild, possibly we need to gather feedback from API users as well if they actually depend on the old behavior, or if this change has uncovered long-standing bugs when planning journeys tomorrow.

@miklcct
Copy link
Contributor

miklcct commented Mar 13, 2025

Also, please don't remove my test. Change it to test the behavior that we have agreed and document it.

@leonardehrenfried
Copy link
Member

I'm assigned the reviewer for this PR. Is there anything for me to do or will it be dropped?

@miklcct
Copy link
Contributor

miklcct commented Mar 20, 2025

Let's discuss if we want to revert to the pre-2.7 non-intuitive behaviour, or if my change actually resulted in hard-to-find bugs discovered in the consumers where they should fix instead.

Unfortunately the damage has been done and people will rightly complain in either case.

@tkalvas
Copy link
Contributor Author

tkalvas commented Mar 20, 2025

Discarded, we will instead just revert the offending PR.

@tkalvas tkalvas closed this Mar 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Digitransit Test Feature is under testing in Digitransit environment(s) Regression This feature is no longer working.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants