Skip to content
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

Refetch transit leg with a leg query of GTFS GraphQL API #6045

Merged
merged 29 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5e18c0a
GTFS graphql API supports querying itinerary leg status
vesameskanen Sep 2, 2024
021e07c
Catch non-transit legs properly
vesameskanen Sep 5, 2024
01b460d
Add type resolver for Leg
vesameskanen Sep 5, 2024
2182066
Fix formatting
vesameskanen Sep 5, 2024
7e2033f
Do not encode null reference as 'null' string
vesameskanen Sep 6, 2024
6b92741
More accurate docs about leg query
vesameskanen Sep 6, 2024
e489f05
Add leg id to plan query test
vesameskanen Sep 6, 2024
6bd5d04
Use self-documenting value for non-transit leg ids
vesameskanen Sep 9, 2024
a998e52
Add more docs about leg re-fetching into gtfs graphql schema
vesameskanen Sep 9, 2024
cf37e89
Support querying leg's realTimeState in GTFS graphql api
vesameskanen Sep 11, 2024
cd54cbe
Query realtimeState in extended plan test
vesameskanen Sep 11, 2024
4025d5b
Revert LegReferenceSerializer changes
vesameskanen Sep 13, 2024
b206ce1
Generate unique id for non-transit legs
vesameskanen Sep 13, 2024
15f1f34
Restore LegReferenceSerializer null test
vesameskanen Sep 13, 2024
20f855a
Update plan-extended expoctations to use unique leg ids
vesameskanen Sep 13, 2024
9b3c4d5
Revert "Generate unique id for non-transit legs"
vesameskanen Sep 24, 2024
14fd13e
Remove node interface from LegType and add leg query
vesameskanen Sep 24, 2024
207cd5d
Merge remote-tracking branch 'otp/dev-2.x' into gfts-leg-node-refetch
vesameskanen Sep 24, 2024
71a6315
Update auto generated files
vesameskanen Sep 24, 2024
cd660b2
Fix schema formatting
vesameskanen Sep 24, 2024
97d2180
Fix leg id access
vesameskanen Sep 24, 2024
b75c047
Remove leg resolver from node type
vesameskanen Sep 24, 2024
1a43221
Use ID parameter type for leg query
vesameskanen Sep 24, 2024
58b382f
Update src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls
vesameskanen Sep 26, 2024
f6a8d8f
Suggested review changes
vesameskanen Sep 26, 2024
71caaa5
Merge remote-tracking branch 'origin/gfts-leg-node-refetch' into gfts…
vesameskanen Sep 26, 2024
ba100e8
Use string type instead of relay ID type for transit leg identification
vesameskanen Sep 27, 2024
45d6f98
Update src/main/java/org/opentripplanner/apis/gtfs/datafetchers/LegIm…
vesameskanen Sep 27, 2024
857b815
Update src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls
vesameskanen Sep 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.opentripplanner.apis.gtfs.datafetchers;

import graphql.relay.Relay;
import graphql.schema.DataFetcher;
vesameskanen marked this conversation as resolved.
Show resolved Hide resolved
import graphql.schema.DataFetchingEnvironment;
import java.util.List;
Expand All @@ -23,6 +24,7 @@
import org.opentripplanner.model.plan.StreetLeg;
import org.opentripplanner.model.plan.TransitLeg;
import org.opentripplanner.model.plan.WalkStep;
import org.opentripplanner.model.plan.legreference.LegReferenceSerializer;
import org.opentripplanner.routing.alertpatch.TransitAlert;
import org.opentripplanner.routing.alternativelegs.AlternativeLegs;
import org.opentripplanner.routing.alternativelegs.AlternativeLegsFilter;
Expand Down Expand Up @@ -189,10 +191,12 @@ public DataFetcher<Boolean> realTime() {
return environment -> getSource(environment).getRealTime();
}

// TODO
@Override
public DataFetcher<String> realtimeState() {
Copy link
Member

Choose a reason for hiding this comment

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

I just realised that this doesn't use a proper mapper, which I think is a very useful thing.

Since I already approved, I wrote the code myself: leonardehrenfried@a763bc5

If you want you can cherry pick it into this PR.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, too late. I will open another one myself.

return environment -> null;
return environment -> {
var state = getSource(environment).getRealTimeState();
return (state != null) ? state.name() : null;
};
}

@Override
Expand Down Expand Up @@ -324,4 +328,16 @@ public DataFetcher<Iterable<Leg>> nextLegs() {
public DataFetcher<Double> accessibilityScore() {
return environment -> NumberMapper.toDouble(getSource(environment).accessibilityScore());
}

@Override
public DataFetcher<Relay.ResolvedGlobalId> id() {
return environment -> {
var ref = getSource(environment).getLegReference();
if (ref == null) {
return null;
}
var id = LegReferenceSerializer.encode(ref);
return new Relay.ResolvedGlobalId("Leg", id);
};
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we should use the global id anymore, since we have own query for this now, we can just return a string which is the output of the LegReferenceSerializer.encode(ref).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using plain string is indeed simpler. Changed.

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore;
import org.opentripplanner.gtfs.mapping.DirectionMapper;
import org.opentripplanner.model.TripTimeOnDate;
import org.opentripplanner.model.plan.Leg;
import org.opentripplanner.model.plan.legreference.LegReference;
import org.opentripplanner.model.plan.legreference.LegReferenceSerializer;
import org.opentripplanner.routing.alertpatch.EntitySelector;
import org.opentripplanner.routing.alertpatch.TransitAlert;
import org.opentripplanner.routing.api.request.RouteRequest;
Expand Down Expand Up @@ -362,6 +365,20 @@ public DataFetcher<Connection<PlaceAtDistance>> nearest() {
};
}

@Override
public DataFetcher<Leg> leg() {
return environment -> {
TransitService transitService = getTransitService(environment);
var args = new GraphQLTypes.GraphQLQueryTypeLegArgs(environment.getArguments());
String id = args.getGraphQLId().getId();
LegReference ref = LegReferenceSerializer.decode(id);
if (ref == null) {
return null;
}
return ref.getLeg(transitService);
};
}

@Override
public DataFetcher<Object> node() {
return environment -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,8 @@ public interface GraphQLLeg {

public DataFetcher<String> headsign();

public DataFetcher<graphql.relay.Relay.ResolvedGlobalId> id();

public DataFetcher<Boolean> interlineWithPreviousLeg();

public DataFetcher<Boolean> intermediatePlace();
Expand Down Expand Up @@ -779,6 +781,8 @@ public interface GraphQLQueryType {

public DataFetcher<Trip> fuzzyTrip();

public DataFetcher<Leg> leg();

public DataFetcher<Connection<PlaceAtDistance>> nearest();

public DataFetcher<Object> node();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2432,6 +2432,25 @@ public void setGraphQLTime(Integer time) {
}
}

public static class GraphQLQueryTypeLegArgs {

private graphql.relay.Relay.ResolvedGlobalId id;

public GraphQLQueryTypeLegArgs(Map<String, Object> args) {
if (args != null) {
this.id = (graphql.relay.Relay.ResolvedGlobalId) args.get("id");
}
}

public graphql.relay.Relay.ResolvedGlobalId getGraphQLId() {
return this.id;
}

public void setGraphQLId(graphql.relay.Relay.ResolvedGlobalId id) {
this.id = id;
}
}

public static class GraphQLQueryTypeNearestArgs {

private String after;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1596,7 +1596,7 @@ private GraphQLSchema create() {
GraphQLFieldDefinition
.newFieldDefinition()
.name("leg")
.description("Refetch a single leg based on its id")
.description("Refetch a single transit leg based on its id")
.withDirective(gqlUtil.timingData)
.type(LegType.REF)
.argument(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ public static GraphQLObjectType create(
GraphQLFieldDefinition
.newFieldDefinition()
.name("id")
.description("An identifier for the leg, which can be used to re-fetch the information.")
.description(
"An identifier for the leg, which can be used to re-fetch transit leg information."
)
.type(Scalars.GraphQLID)
.dataFetcher(env -> LegReferenceSerializer.encode(leg(env).getLegReference()))
.build()
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/org/opentripplanner/model/plan/Leg.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.opentripplanner.transit.model.organization.Agency;
import org.opentripplanner.transit.model.organization.Operator;
import org.opentripplanner.transit.model.site.FareZone;
import org.opentripplanner.transit.model.timetable.RealTimeState;
import org.opentripplanner.transit.model.timetable.Trip;
import org.opentripplanner.transit.model.timetable.TripOnServiceDate;
import org.opentripplanner.transit.model.timetable.booking.BookingInfo;
Expand Down Expand Up @@ -244,6 +245,10 @@ default boolean getRealTime() {
return false;
}

default RealTimeState getRealTimeState() {
return null;
}

/**
* Whether this Leg describes a flexible trip. The reason we need this is that FlexTrip does not
* inherit from Trip, so that the information that the Trip is flexible would be lost when
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.opentripplanner.transit.model.organization.Agency;
import org.opentripplanner.transit.model.organization.Operator;
import org.opentripplanner.transit.model.site.StopLocation;
import org.opentripplanner.transit.model.timetable.RealTimeState;
import org.opentripplanner.transit.model.timetable.Trip;
import org.opentripplanner.transit.model.timetable.TripOnServiceDate;
import org.opentripplanner.transit.model.timetable.TripTimes;
Expand Down Expand Up @@ -227,6 +228,11 @@ public boolean getRealTime() {
);
}

@Override
public RealTimeState getRealTimeState() {
return tripTimes.getRealTimeState();
}

@Override
public double getDistanceMeters() {
return distanceMeters;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,12 @@ type Leg {
"""
headsign: String
"""
An identifier for the leg, which can be used to re-fetch transit leg information.
Re-fetching fails when the underlying transit data no longer exists.
Non-transit legs cannot be refetched using their id.
vesameskanen marked this conversation as resolved.
Show resolved Hide resolved
"""
id: ID
vesameskanen marked this conversation as resolved.
Show resolved Hide resolved
"""
Interlines with previous leg.
This is true when the same vehicle is used for the previous leg as for this leg
and passenger can stay inside the vehicle.
Expand Down Expand Up @@ -1166,6 +1172,11 @@ type QueryType {
time: Int!
): Trip
"""
Try refetching the current state of a transit leg using its ID.
This fails when the underlying transit data (mostly IDs) has changed or are no longer available.
"""
leg(id: ID!): Leg
vesameskanen marked this conversation as resolved.
Show resolved Hide resolved
"""
Get all places (stops, stations, etc. with coordinates) within the specified
radius from a location. The returned type is a Relay connection (see
https://facebook.github.io/relay/graphql/connections.htm). The placeAtDistance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ type Leg {
fromPlace: Place!
"Generalized cost or weight of the leg. Used for debugging."
generalizedCost: Int
"An identifier for the leg, which can be used to re-fetch the information."
"An identifier for the leg, which can be used to re-fetch transit leg information."
id: ID
interchangeFrom: Interchange
interchangeTo: Interchange
Expand Down Expand Up @@ -647,7 +647,7 @@ type QueryType {
groupOfLines(id: String!): GroupOfLines
"Get all groups of lines"
groupsOfLines: [GroupOfLines!]!
"Refetch a single leg based on its id"
"Refetch a single transit leg based on its id"
leg(id: ID!): Leg @timingData
"Get a single line based on its id"
line(id: ID!): Line @timingData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@
"intermediatePlaces" : null,
"alerts" : [ ],
"rideHailingEstimate" : null,
"accessibilityScore" : null
"accessibilityScore" : null,
"id": null,
"realtimeState": null
},
{
"mode" : "BUS",
Expand Down Expand Up @@ -154,7 +156,9 @@
],
"alerts" : [ ],
"rideHailingEstimate" : null,
"accessibilityScore" : null
"accessibilityScore" : null,
"id": "TGVnOnJPMEFCWGRCQUJoVFEwaEZSRlZNUlVSZlZGSkJUbE5KVkY5TVJVZGZWak1BQlVZNk1USXlBQW95TURJd0xUQXlMVEF5QUFBQUJRQUFBQWNBQTBZNlFnQURSanBEQUFBPQ",
"realtimeState": "UPDATED"
},
{
"mode" : "RAIL",
Expand Down Expand Up @@ -264,7 +268,9 @@
}
],
"rideHailingEstimate" : null,
"accessibilityScore" : null
"accessibilityScore" : null,
"id": "TGVnOnJPMEFCWGRCQUJoVFEwaEZSRlZNUlVSZlZGSkJUbE5KVkY5TVJVZGZWak1BQlVZNk5ETTVBQW95TURJd0xUQXlMVEF5QUFBQUJRQUFBQWNBQTBZNlF3QURSanBFQUFBPQ",
"realtimeState": "UPDATED"
},
{
"mode" : "CAR",
Expand Down Expand Up @@ -334,11 +340,13 @@
},
"arrival" : "PT10M"
},
"accessibilityScore" : null
"accessibilityScore" : null,
"id": null,
"realtimeState": null
}
]
}
]
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@
arrival
}
accessibilityScore
id
realtimeState
}
}
}
Expand Down
Loading