Skip to content

Store all alerts and add support for route_type and direction_id selectors - #3780

Merged
optionsome merged 29 commits into
opentripplanner:dev-2.xfrom
HSLdevcom:alert-entity-updates
Jan 25, 2022
Merged

Store all alerts and add support for route_type and direction_id selectors#3780
optionsome merged 29 commits into
opentripplanner:dev-2.xfrom
HSLdevcom:alert-entity-updates

Conversation

@optionsome

@optionsome optionsome commented Dec 13, 2021

Copy link
Copy Markdown
Member

Summary

  • Add support for route_type and direction_id selectors
  • Store entities with no or unhandled entity selectors with Unknown entity selector so they are kept instead of ignored
    • Currently for SIRI, only do this at the end of processing an alert so the case of no entitiy selectors or known entity selectors is handled as one Unknown selector
  • Implement alert functionality in Legacy GraphQL API
    • Add RouteType, DirectionOnRoute and Unknown types that are used as alert entitites
    • Implement alerts fields and add types parameter with array of enum options
    • Add alerts field to feed

Issue

closes #3779, #3486

Unit tests

Added unit tests for the alert updaters

Code style

Have you followed the suggested code style?
Yes

Documentation

Is there some documentation that should be updated?

Changelog

From title and added changelog for sandbox features

@optionsome
optionsome requested a review from a team as a code owner December 13, 2021 09:15

@optionsome optionsome left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm a bit unsure if we should store the alerts with the original selectors and expose them through APIs that way or, for example, create as many pattern selectors as there are patterns for a direction in route's direction and expose the route_id+direction_id alerts directly through the pattern/trip types in APIs and hide the original selector structure from the API users. I think there are some use cases where users would want to display alerts that are targeted for a "super type" that covers multiple "entities" differently than when an alert is directly targeted for an individual entity.

TripPattern tripPattern = getRoutingService(environment).getTripPatternForId(id);
return getAlertEntityOrUnknown(tripPattern, id.toString(), "trip pattern");
}
if (entitySelector instanceof EntitySelector.StopAndRoute) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We could also validate that the stop is actually on the route/trip but I think it's a valid use case that you create an alert "Route x no longer stops at stop y" and want to display that on route, for example.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Decided that alerts should have the original XandY entity type even though they are not really linked together (anymore).

trip -> alerts.addAll(alertService.getTripAlerts(trip.getId(), null)));
break;
case StopsOnRoute:
getStops(environment).forEach(stop -> {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

After I implemented this so it checks that the alerts for stops that are on route, I realised that maybe it would make sense to just fetch all StopAndRoute type alerts that have the route defined here as it might be useful to display alerts that warn that a stop is no longer on the route, for example.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Changed this so that the stop doesn't need to be on the route/trip/pattern nor do the route/trip have to go through the stop in order to return these StopAndRoute/Trip alerts.

situationNumber
);
}
alert.addEntity(new EntitySelector.Unknown("Alert had no entities that could be handled"));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Maybe it would also be possible to add Unknown selector each time a selector was ignored because we don't handle it yet instead of adding one Unknown selector at the end like this.

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.

Should the "add unknown entity" be inside the if-block?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Indeed... I'll fix that and update tests a bit so they will catch if suddenly new entities appear.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed it now and changed tests so that they test that only the intended entities get added instead of checking that x type entities don't get added.

Direction on a route. In practice,
this means the trips/patterns of a route that have the defined direction.
"""
type DirectionOnRoute {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Maybe it would be useful to expose the affected trips/patterns through this type.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removed this type and instead generated Pattern selectors from the DirectionAndRoute entity selector.

Route type entity which covers all agencies if agency is null,
otherwise only relevant for one agency.
"""
type RouteType {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Maybe it would be useful to expose the affected routes through this type.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Implemented this.

} else {
direction = -1;
int directionId = MISSING_INT_FIELD_VALUE;
if (informed.hasDirectionId()) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Should we also handle informed.getTrip().getDirectionId() here. I'm not quite sure what is the difference between them other than that the trip descriptor's direction was added to the spec first(?). I have a feeling that the trip descriptor's directionId should be used for fuzzy trip matching to find individual trips instead of using it just together with the route_id.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We decided that the TripDescriptor's direction_id should only be used for fuzzy matching.

new FeedScopedId(feedId, routeId)
));
} else if (directionId != MISSING_INT_FIELD_VALUE) {
alertText.addEntity(new EntitySelector.DirectionAndRoute(

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I decided to add this new DirectionAndRoute type instead of using the Pattern selector. The pattern selector is not being used for anything, can it be removed or should this be changed to use it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removed TripPattern entity selector as it is not being used for anything and couldn't think of a way it could be used in the near future either.

@t2gran t2gran added this to the 2.1 milestone Dec 13, 2021
@t2gran t2gran added !New Feature A functional feature targeting the end user. Regression labels Dec 16, 2021

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

I would really like to see the filter logic being made a lot more readable by reducing the multi-line, multi-indented filter functions into smaller bits.

Also, I think the filter classes can share a significant part of the code. I see lots of repetition.

Comment thread src/ext-test/java/org/opentripplanner/ext/siri/SiriAlertsUpdateHandlerTest.java Outdated
@t2gran

t2gran commented Jan 6, 2022

Copy link
Copy Markdown
Member

We discussed this PR today, at the developer meeting. I agree with @leonardehrenfried that both GraphQL APIs is kind of ugly, but I hope we can get rid of them, not too long time into the future. They are also both considered "Sandbox" features so I am unsure if they are the right place to spent time cleaning up.

@optionsome wrote:

I'm a bit unsure if we should store the alerts with the original selectors and expose them through APIs that way or, for example, create as many pattern selectors as there are patterns for a direction in route's direction and expose the route_id+direction_id alerts directly through the pattern/trip types in APIs and hide the original selector structure from the API users. I think there are some use cases where users would want to display alerts that are targeted for a "super type" that covers multiple "entities" differently than when an alert is directly targeted for an individual entity.

I can only give a general advice here, but this what I think: OTP is a travel planner and we keep some relevant information (like the Index API). To solve the problem (OTP features) we sometimes transform input models(pattern selectors) into simpler or easier to work with data structures - if these are not sufficient to recreate the input, then we kindly ask the consumer requesting the information to look at the input instead. @optionsome you know much better than me, what is right in this case. You have my support if you want to reduce the "information value" if that lead to a simpler API for most clients or the maintenance of OTP become easier.

@optionsome

Copy link
Copy Markdown
Member Author

Indeed there is a lot of room for improvement in the GraphQL API code, both to make it more readable and also to optimize the performance. I was aware while writing this code that at least some parts of it need to be rewritten soon anyway as @t2gran said, therefore I didn't spend too much time on polishing the code. We should consider @leonardehrenfried 's comments when implementing the new API but I also feel like that maybe we shouldn't spend too much time on improving the legacy GraphQL API at this point.

I refactored the siri test changes as it was easy to do while keeping it still simple to read hopefully 2eb024a.

@optionsome

optionsome commented Jan 7, 2022

Copy link
Copy Markdown
Member Author

Does anyone have a clue why the code suddenly doesn't build in github actions? I only touched some tests a bit after last successful build and locally it compiles for me at least?

@t2gran
t2gran self-requested a review January 11, 2022 10:32
@t2gran t2gran added the +Sandbox This will be implemented as a Sandbox feature label Jan 13, 2022

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

I do not have much to contribute here, but as @leonardehrenfried alreaddy pointed out there are some repetition between the two APIs - and it seem that the APIs also do quite a bit of generic business logic - if so that logic belongs in the core of OTP, not in the API mapping.

A good guidance is that logic witch is use-case specific should remain in the API mappers while reusable logic should be pushed to domain model. We can do this cleanup as part of this PR or later, when doing the new API.

@t2gran
t2gran dismissed leonardehrenfried’s stale review January 25, 2022 10:12

We will clean up the APIs when working on the new API

@optionsome
optionsome merged commit bc6cc6d into opentripplanner:dev-2.x Jan 25, 2022
@optionsome
optionsome deleted the alert-entity-updates branch January 25, 2022 10:13
t2gran pushed a commit that referenced this pull request Jan 25, 2022
@t2gran t2gran removed the Regression label Sep 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

!New Feature A functional feature targeting the end user. +Sandbox This will be implemented as a Sandbox feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Alerts with no or no handled entities selectors should be stored instead of completely ignored

5 participants