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

Add and update Javadoc on realtime classes #5585

Merged
merged 27 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0b8dfc6
add javadoc to some realtime classes
abyrd Dec 15, 2023
2bb60a0
add a few incomplete javadoc ideas
abyrd Dec 15, 2023
3f79a1d
javadoc and code comment updates
abyrd Dec 18, 2023
7a0b56d
chain builder methods
abyrd Dec 18, 2023
a0c18f4
add javadoc (incl. uncertain and open questions)
abyrd Dec 20, 2023
710b678
Add more Javadoc and questions to realtime code
abyrd Jan 21, 2024
3b94c8f
code formatting with mvn prettier:write
abyrd Jan 24, 2024
0cc8c40
Merge remote-tracking branch 'origin/dev-2.x' into abyrd/realtime-jav…
abyrd Feb 22, 2024
873ceec
add realtime updater concurrency diagram and md
abyrd Feb 22, 2024
e3b5326
update realtime concurrency diagram
abyrd Feb 22, 2024
c23038e
add data sources and incrementality sections
abyrd Feb 23, 2024
79de961
add design considerations section
abyrd Feb 23, 2024
9c342a6
Merge branch 'dev-2.x' into abyrd/realtime-javadoc
abyrd Mar 12, 2024
94fea1d
More cleanup of all RT comments
abyrd Mar 12, 2024
a92917b
remove draft code
abyrd Mar 14, 2024
d5dbf79
Update src/main/java/org/opentripplanner/routing/graph/Graph.java
abyrd Mar 31, 2024
50bd252
update docs in response to PR comments
abyrd Mar 31, 2024
74430b0
Apply suggestions from code review
abyrd May 3, 2024
31dc110
updates in response to PR review
abyrd May 3, 2024
871c9c2
Update javadoc in response to PR review
abyrd May 3, 2024
e0f74f1
formatting (mvn prettier:write)
abyrd May 3, 2024
0764267
Update updater/package.md
abyrd May 3, 2024
97d99b0
Update src/main/java/org/opentripplanner/updater/package.md
abyrd May 4, 2024
f4a23d8
update package.md in response to PR review
abyrd May 4, 2024
ce31c8e
Apply suggestions from code review
abyrd May 17, 2024
c66d301
update comments in response to review
abyrd May 17, 2024
df3361f
Merge remote-tracking branch 'origin/dev-2.x' into abyrd/realtime-jav…
abyrd May 17, 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
Expand Up @@ -35,18 +35,26 @@
import uk.org.siri.siri20.WorkflowStatusEnumeration;

/**
* This updater applies the equivalent of GTFS Alerts, but from SIRI Situation Exchange feeds. NOTE
* this cannot handle situations where there are multiple feeds with different IDs (for now it may
* only work in single-feed regions).
* This updater applies the equivalent of GTFS Alerts, but from SIRI Situation Exchange feeds.
* TODO RT_AB: The name should be clarified, as there is no such thing as "SIRI Alerts", and it
* is referencing the internal model concept of "Alerts" which are derived from GTFS terminology.
* NOTE this cannot handle situations where incoming messages are being applied to multiple static
* feeds with different IDs (for now it may only work in single-feed regions).
abyrd marked this conversation as resolved.
Show resolved Hide resolved
*/
public class SiriAlertsUpdateHandler {

private static final Logger LOG = LoggerFactory.getLogger(SiriAlertsUpdateHandler.class);
private final String feedId;
private final Set<TransitAlert> alerts = new HashSet<>();
private final TransitAlertService transitAlertService;
/** How long before the posted start of an event it should be displayed to users */

/** The alert should be displayed to users this long before the activePeriod begins. */
Copy link
Member

Choose a reason for hiding this comment

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

Java doc should not be added to private fields, but the get (or set) accessor.

Copy link
Member Author

@abyrd abyrd May 3, 2024

Choose a reason for hiding this comment

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

In this case, the private field can only be set via the constructor. The comment can be moved to the constructor but then for a maintainer working on the internals of this class to understand what the earlyStart field does, they'd need to find that it's set in the constructor, read the constructor javadoc, and confirm that the documented constructor parameter sets this field.

I get the idea of wanting the documentation concentrated on public methods, but I think it depends whether the documentation is intended for developers working on this code, or for developers making use of the code. In a case like this I'd be inclined to duplicate the documentation - maintenance can cross a line to being very tedious when the reader has to go searching for the meaning of every field.

Some DRY could be achieved by linking the private field Javadoc to the only place it's set, but this requires a verbose approach that is just as long as the comment explaining the purpose of the field, and much more fragile/full of irrelevant detail:
/** @see #SiriAlertsUpdateHandler(String, TransitModel, TransitAlertService, SiriFuzzyTripMatcher, Duration) */

I also find there's something non-generalizable about a convention of documenting on an accessor method because the relationship from fields to methods that mutate them is one-to-many. There's not one unambiguous place to put the documentation (on a setter, a factory method, one of several constructors?) but there is a single field they're all referencing.

Copy link
Member Author

Choose a reason for hiding this comment

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

I moved it to an @see annotation on the constructor javadoc.

private final Duration earlyStart;
t2gran marked this conversation as resolved.
Show resolved Hide resolved

/**
* This takes the parts of the SIRI SX message saying which transit entities are affected and
* maps them to the corresponding OTP internal model entity or entities.
*/
private final AffectsMapper affectsMapper;

public SiriAlertsUpdateHandler(
Expand Down Expand Up @@ -120,6 +128,12 @@ public void update(ServiceDelivery delivery) {
}
}

/**
* FIXME RT_AB: This does not just "handle" an alert, it builds an internal model Alert from
* an incoming SIRI situation exchange element. It is a mapper or factory.
* It may return null if the header, description, and detail text are all empty or missing in the
* SIRI message. In all other cases it will return a valid TransitAlert instance.
*/
abyrd marked this conversation as resolved.
Show resolved Hide resolved
private TransitAlert handleAlert(PtSituationElement situation) {
TransitAlertBuilder alert = createAlertWithTexts(situation);

Expand Down Expand Up @@ -199,7 +213,9 @@ private long getEpochSecond(ZonedDateTime startTime) {
}

/*
* Creates alert from PtSituation with all textual content
* Creates a builder for an internal model TransitAlert, including all textual content from the
* supplied SIRI PtSituation. The feed scoped ID of this TransitAlert will be the single feed ID
* associated with this update handler, plus the situation number provided in the SIRI feed.
Copy link
Member

Choose a reason for hiding this comment

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

The feed scoped ID of this TransitAlert will be the single feed ID
associated with this update handler, plus the situation number provided in the SIRI feed.

The strategy for handling IDs should be documented in a more visible place than on a private method. I also think we probably need to allow more than one strategy - so it should be extracted so it is pluggable. This is probably one of the main things we need to fix to more this from the Sandbox to the main code.

Copy link
Member Author

Choose a reason for hiding this comment

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

From a maintenance perspective, this may be a good place to document the structure of the IDs because they are created during this mapping operation. Although I value DRY, the same concern exists here as other places above: increasing visibility of docs for people reusing/configuring the encapsulated code might make it hard for the maintainer to find those descriptions and use them to quickly understand the actions of this method.

Copy link
Member Author

Choose a reason for hiding this comment

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

I have also put the information in the class-level Javadoc, and rephrased the information for the two contexts. Also included a note that FeedScopedId creation strategy should be pluggable or configurable as a condition for moving out of sandbox.

*/
private TransitAlertBuilder createAlertWithTexts(PtSituationElement situation) {
return TransitAlert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,13 @@ public TimetableSnapshot getTimetableSnapshot() {

/**
* Method to apply a trip update list to the most recent version of the timetable snapshot.
* FIXME RT_AB: TripUpdate is the GTFS term, and these SIRI ETs are never converted into that
* same internal model.
*
* @param fullDataset true iff the list with updates represent all updates that are active right
* now, i.e. all previous updates should be disregarded
* @param updates SIRI VehicleMonitoringDeliveries that should be applied atomically
* FIXME RT_AB: aren't these ET deliveries, not VM?
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
* @param updates SIRI VehicleMonitoringDeliveries that should be applied atomically
* FIXME RT_AB: aren't these ET deliveries, not VM?

There is no information here, then it is better to delete the comment.

Copy link
Member Author

Choose a reason for hiding this comment

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

Some of the comments in this PR were tracking things I was not sure about, or queueing up to investigate. I didn't want to commit definitive statements or remove docs until I was sure of what I was seeing. In this case I think the Javadoc seemed so out of place that I was questioning my own interpretation. Maybe the code was just copied without changing the documentation. Looking at it again, these are clearly ET and not VM so I updated the comment.

*/
public UpdateResult applyEstimatedTimetable(
@Nullable SiriFuzzyTripMatcher fuzzyTripMatcher,
Expand Down Expand Up @@ -373,11 +376,10 @@ private Result<UpdateSuccess, UpdateError> addTripToGraphAndBuffer(TripUpdate tr
serviceDate
);

// Add new trip times to the buffer and return success
// Add new trip times to the buffer and return result with success or error. The update method
// will perform protective copies as needed, whether pattern is created by realtime data or not.
Copy link
Member

Choose a reason for hiding this comment

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

The update method will perform protective copies as needed, whether pattern is created by realtime data or not.

Consider pushing this into the JavaDoc on the update method.

Copy link
Member Author

Choose a reason for hiding this comment

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

From a maintenance perspective, it can be very helpful to have an inline narrative of what a method is doing including some non-obvious details, without needing to read and piece together the details of each called method's own documentation. I generally added comments like this for details that tripped me up, which I thought could help future comprehension or refactoring.

I have moved the new detail about the behavior of the called method into that method's Javadoc, while keeping a one-line note here in the caller.

var result = buffer.update(pattern, tripUpdate.tripTimes(), serviceDate);

LOG.debug("Applied real-time data for trip {} on {}", trip, serviceDate);

return result;
}

Expand Down
161 changes: 106 additions & 55 deletions src/ext/java/org/opentripplanner/ext/siri/SiriTripPatternCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,57 @@
import javax.annotation.Nonnull;
import org.opentripplanner.transit.model.network.StopPattern;
import org.opentripplanner.transit.model.network.TripPattern;
import org.opentripplanner.transit.model.network.TripPatternBuilder;
import org.opentripplanner.transit.model.site.RegularStop;
import org.opentripplanner.transit.model.site.StopLocation;
import org.opentripplanner.transit.model.timetable.Trip;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A synchronized cache of trip patterns that are added to the graph due to GTFS-realtime messages.
* Threadsafe mechanism for tracking any TripPatterns added to the graph via SIRI realtime messages.
* This tracks only patterns added by realtime messages, not ones that already existed from the
* scheduled NeTEx. This is a "cache" in the sense that it will keep returning the same TripPattern
* when presented with the same StopPattern, so if realtime messages add many trips passing through
* the same sequence of stops, they will all end up on this same TripPattern.
* <p>
* Note that there are two versions of this class, this one for GTFS-RT and another for SIRI.
* See additional comments in the Javadoc of the GTFS-RT version of this class, whose name is
* simply TripPatternCache.
* TODO RT_AB: To the extent that double SIRI/GTFS implementations are kept, prefix all names
* with GTFS or SIRI or NETEX rather than having no prefix on the GTFS versions.
*/
abyrd marked this conversation as resolved.
Show resolved Hide resolved
public class SiriTripPatternCache {

private static final Logger log = LoggerFactory.getLogger(SiriTripPatternCache.class);
private static final Logger LOG = LoggerFactory.getLogger(SiriTripPatternCache.class);

// TODO RT_AB: Improve documentation. This seems to be the primary collection of added
// TripPatterns, with other collections serving as indexes. Similar to TripPatternCache.cache
// in the GTFS version of this class, but with service date as part of the key.
private final Map<StopPatternServiceDateKey, TripPattern> cache = new HashMap<>();

// This appears to be a SIRI-specific index for use in GraphQL APIs.
// It is not present on the GTFS-RT version of this class.
Copy link
Member

Choose a reason for hiding this comment

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

I would guess this is used by the "Transmodel API", not SIRI - but have not looked into it. Note! APIs should work/be independent of data provider(s).

Copy link
Member Author

@abyrd abyrd May 3, 2024

Choose a reason for hiding this comment

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

What I meant here is that this class exists in two versions (SiriTripPatternCache and the non-SIRI TripPatternCache i.e. GTFS version) and the following field looks like an index that only exists on the SiriTripPatternCache. Indeed, maybe the SiriTripPatternCache is not really about SIRI but just an Entur fork of the TripPatternCache which happens to be Transmodel-oriented. However, I think this these TripPatternCache classes do exist primarily or only to track entities created in real time, and this may be effectively restricted to SIRI sources (it's not clear for the reader).

This further emphasizes the naming and code divergence problems we've discussed before: the name of the class gives the impression there's something SIRI-specific about it, and implies there's some reason tracking TripPatterns created in real time would be different for SIRI and GTFS-RT sources. But really this is probably just due to forking classes to accelerate development.

I will update this comment to make it a little more clear.

private final ListMultimap<StopLocation, TripPattern> patternsForStop = Multimaps.synchronizedListMultimap(
ArrayListMultimap.create()
);

// TODO RT_AB: clarify name and add documentation to this field.
private final Map<TripServiceDateKey, TripPattern> updatedTripPatternsForTripCache = new HashMap<>();

// TODO RT_AB: generalize this so we can generate IDs for SIRI or GTFS-RT sources.
private final SiriTripPatternIdGenerator tripPatternIdGenerator;

/**
* SiriTripPatternCache needs only this one feature of TransitService, so we retain only this
* function reference to effectively narrow the interface. This should also facilitate testing.
*/
abyrd marked this conversation as resolved.
Show resolved Hide resolved
private final Function<Trip, TripPattern> getPatternForTrip;

/**
* Constructor.
* TODO RT_AB: This class could potentially be reused for both SIRI and GTFS-RT, which may
* involve injecting a different ID generator and pattern fetching method.
*/
abyrd marked this conversation as resolved.
Show resolved Hide resolved
public SiriTripPatternCache(
SiriTripPatternIdGenerator tripPatternIdGenerator,
Function<Trip, TripPattern> getPatternForTrip
Expand All @@ -45,9 +71,16 @@ public SiriTripPatternCache(
this.getPatternForTrip = getPatternForTrip;
}

//

abyrd marked this conversation as resolved.
Show resolved Hide resolved
/**
* Get cached trip pattern or create one if it doesn't exist yet. If a trip pattern is created,
* vertices and edges for this trip pattern are also created in the transitModel.
* Get cached trip pattern or create one if it doesn't exist yet.
*
* TODO RT_AB: Improve documentation and/or merge with GTFS version of this class.
* This was clearly derived from a method from TripPatternCache. This is the only non-dead-code
* public method on this class, and mirrors the only public method on the GTFS-RT version of
* TripPatternCache. It also explains why this class is called a "cache". It allows reusing the
* same TripPattern instance when many different trips are created or updated with the same pattern.
*
* @param stopPattern stop pattern to retrieve/create trip pattern
* @param trip Trip containing route of new trip pattern in case a new trip pattern will be
Expand All @@ -61,6 +94,9 @@ public synchronized TripPattern getOrCreateTripPattern(
) {
TripPattern originalTripPattern = getPatternForTrip.apply(trip);

// TODO RT_AB: Verify implementation, which is different than the GTFS-RT version.
// It can return a TripPattern from the scheduled data, but protective copies are handled in
// TimetableSnapshot.update. Better document this aspect of the contract in this method's Javadoc.
if (originalTripPattern.getStopPattern().equals(stopPattern)) {
return originalTripPattern;
}
Expand All @@ -72,56 +108,57 @@ public synchronized TripPattern getOrCreateTripPattern(
// Create TripPattern if it doesn't exist yet
if (tripPattern == null) {
var id = tripPatternIdGenerator.generateUniqueTripPatternId(trip);
TripPatternBuilder tripPatternBuilder = TripPattern
.of(id)
.withRoute(trip.getRoute())
.withMode(trip.getMode())
.withNetexSubmode(trip.getNetexSubMode())
.withStopPattern(stopPattern);

// TODO - SIRI: Add pattern to transitModel index?

tripPatternBuilder.withCreatedByRealtimeUpdater(true);
tripPatternBuilder.withOriginalTripPattern(originalTripPattern);

tripPattern = tripPatternBuilder.build();
tripPattern =
TripPattern
.of(id)
.withRoute(trip.getRoute())
.withMode(trip.getMode())
.withNetexSubmode(trip.getNetexSubMode())
.withStopPattern(stopPattern)
.withCreatedByRealtimeUpdater(true)
.withOriginalTripPattern(originalTripPattern)
.build();
// TODO: Add pattern to transitModel index?

// Add pattern to cache
cache.put(key, tripPattern);
}

/**
*
* When the StopPattern is first modified (e.g. change of platform), then updated (or vice versa), the stopPattern is altered, and
* the StopPattern-object for the different states will not be equal.
*
* This causes both tripPatterns to be added to all unchanged stops along the route, which again causes duplicate results
* in departureRow-searches (one departure for "updated", one for "modified").
*
* Full example:
* Planned stops: Stop 1 - Platform 1, Stop 2 - Platform 1
*
* StopPattern #rt1: "updated" stopPattern cached in 'patternsForStop':
* - Stop 1, Platform 1
* - StopPattern #rt1
* - Stop 2, Platform 1
* - StopPattern #rt1
*
* "modified" stopPattern: Stop 1 - Platform 1, Stop 2 - Platform 2
*
* StopPattern #rt2: "modified" stopPattern cached in 'patternsForStop' will then be:
* - Stop 1, Platform 1
* - StopPattern #rt1, StopPattern #rt2
* - Stop 2, Platform 1
* - StopPattern #rt1
* - Stop 2, Platform 2
* - StopPattern #rt2
*
*
* Therefore, we must cleanup the duplicates by deleting the previously added (and thus outdated)
* tripPattern for all affected stops. In example above, "StopPattern #rt1" should be removed from all stops
*
*/
/*
When the StopPattern is first modified (e.g. change of platform), then updated (or vice
versa), the stopPattern is altered, and the StopPattern-object for the different states will
not be equal.

This causes both tripPatterns to be added to all unchanged stops along the route, which again
causes duplicate results in departureRow-searches (one departure for "updated", one for
"modified").

Full example:
Planned stops: Stop 1 - Platform 1, Stop 2 - Platform 1

StopPattern #rt1: "updated" stopPattern cached in 'patternsForStop':
- Stop 1, Platform 1
- StopPattern #rt1
- Stop 2, Platform 1
- StopPattern #rt1

"modified" stopPattern: Stop 1 - Platform 1, Stop 2 - Platform 2

StopPattern #rt2: "modified" stopPattern cached in 'patternsForStop' will then be:
- Stop 1, Platform 1
- StopPattern #rt1, StopPattern #rt2
- Stop 2, Platform 1
- StopPattern #rt1
- Stop 2, Platform 2
- StopPattern #rt2

Therefore, we must clean up the duplicates by deleting the previously added (and thus
outdated) tripPattern for all affected stops. In example above, "StopPattern #rt1" should be
removed from all stops.

TODO RT_AB: review why this particular case is handled in an ad-hoc manner. It seems like all
such indexes should be constantly rebuilt and versioned along with the TimetableSnapshot.
*/
TripServiceDateKey tripServiceDateKey = new TripServiceDateKey(trip, serviceDate);
if (updatedTripPatternsForTripCache.containsKey(tripServiceDateKey)) {
// Remove previously added TripPatterns for the trip currently being updated - if the stopPattern does not match
Expand All @@ -132,16 +169,14 @@ public synchronized TripPattern getOrCreateTripPattern(
patternsForStop.values().removeAll(Arrays.asList(cachedTripPattern));
int sizeAfter = patternsForStop.values().size();

log.debug(
LOG.debug(
"Removed outdated TripPattern for {} stops in {} ms - tripId: {}",
(sizeBefore - sizeAfter),
(System.currentTimeMillis() - t1),
trip.getId()
);
/*
TODO: Also remove previously updated - now outdated - TripPattern from cache ?
cache.remove(new StopPatternServiceDateKey(cachedTripPattern.stopPattern, serviceDate));
*/
// TODO: Also remove previously updated - now outdated - TripPattern from cache ?
// cache.remove(new StopPatternServiceDateKey(cachedTripPattern.stopPattern, serviceDate));
}
}

Expand All @@ -160,6 +195,7 @@ public synchronized TripPattern getOrCreateTripPattern(

/**
* Returns any new TripPatterns added by real time information for a given stop.
* TODO RT_AB: this appears to be currently unused. Perhaps remove it if the API has changed.
*
* @param stop the stop
* @return list of TripPatterns created by real time sources for the stop.
Expand All @@ -169,6 +205,16 @@ public List<TripPattern> getAddedTripPatternsForStop(RegularStop stop) {
}
}

// TODO RT_AB: move the below classes inside the above class as private static inner classes.
// Defining these additional classes in the same top-level class file is unconventional.

/**
* Serves as the key for the collection of TripPatterns added by realtime messages.
* Must define hashcode and equals to confer semantic identity.
* TODO RT_AB: clarify why each date has a different TripPattern instead of a different Timetable.
* It seems like there's a separate TripPattern instance for each StopPattern and service date,
* rather a single TripPattern instance associated with a separate timetable for each date.
*/
class StopPatternServiceDateKey {

StopPattern stopPattern;
Expand All @@ -194,6 +240,11 @@ public boolean equals(Object thatObject) {
}
}

/**
* An alternative key for looking up realtime-added TripPatterns by trip and service date instead
* of stop pattern and service date. Must define hashcode and equals to confer semantic identity.
* TODO RT_AB: verify whether one map is considered the definitive collection and the other an index.
*/
class TripServiceDateKey {

Trip trip;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,19 @@
import org.opentripplanner.transit.model.timetable.Trip;

/**
* This class generate a new id for new TripPatterns created real-time by the SIRI updaters. It is
* important to creat only on instance of this class, and inject it where it is needed.
* <p>
* The id generation is thread-safe, even if that is probably not needed.
* This class generates new unique IDs for TripPatterns created in response to real-time updates
* from the SIRI updaters. It is important to create only one instance of this class, and inject
* that single instance wherever it is needed. The ID generation is threadsafe, even if that is
* probably not needed.
abyrd marked this conversation as resolved.
Show resolved Hide resolved
*/
class SiriTripPatternIdGenerator {

private final AtomicInteger counter = new AtomicInteger(0);

/**
* Generate unique trip pattern code for real-time added trip pattern. This function roughly
* follows the format of {@link GenerateTripPatternsOperation}.
* <p>
* The generator add a postfix 'RT' to indicate that this trip pattern is generated at REAL-TIME.
* Generate a unique ID for a trip pattern added in response to a realtime message. This function
* roughly follows the format of {@link GenerateTripPatternsOperation}. The generator suffixes the
* ID with 'RT' to indicate that this trip pattern is generated in response to a realtime message.
*/
FeedScopedId generateUniqueTripPatternId(Trip trip) {
Route route = trip.getRoute();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@

/**
* Maps a {@link AffectsScopeStructure} to a list of {@link EntitySelector}s
*
* Concretely: this takes the parts of the SIRI SX (Alerts) message describing which transit
* entities are concerned by the alert, and maps them to EntitySelectors, which can match multiple
* OTP internal model entities that should be associated with the message.
*/
public class AffectsMapper {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
import java.util.Optional;
import uk.org.siri.siri20.Siri;

/**
* Interface for a blocking, polling approach to retrieving SIRI realtime timetable updates.
* TODO RT_AB: Clearly document whether the methods should return as fast as possible, or if they
* should intentionally block and wait for refreshed data, and how this fits into the design.
*/
public interface EstimatedTimetableSource {
/**
* Wait for one message to arrive, and decode it into a List of TripUpdates. Blocking call.
Expand Down
Loading
Loading