-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Conditionally wait for previous polling task #6401
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
Changes from 2 commits
60b9dcc
55aae1f
1779d22
3da1242
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |||||
| import java.time.Duration; | ||||||
| import java.util.concurrent.CancellationException; | ||||||
| import java.util.concurrent.ExecutionException; | ||||||
| import java.util.concurrent.Future; | ||||||
| import org.opentripplanner.framework.application.OTPFeature; | ||||||
| import org.opentripplanner.updater.GraphWriterRunnable; | ||||||
| import org.slf4j.Logger; | ||||||
|
|
@@ -40,7 +41,15 @@ public abstract class PollingGraphUpdater implements GraphUpdater { | |||||
| /** | ||||||
| * Parent update manager. Is used to execute graph writer runnables. | ||||||
| */ | ||||||
| protected WriteToGraphCallback saveResultOnGraph; | ||||||
| private WriteToGraphCallback saveResultOnGraph; | ||||||
|
|
||||||
| /** | ||||||
| * Handle on the task posted during the previous polling execution. | ||||||
|
||||||
| * Handle on the task posted during the previous polling execution. | |
| * A Future representing pending completion of most recently submitted task. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add @nullable here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The system in this PR where this method is called from runPolling() in all subclasses, with this method being the sole way to submit tasks to a private WriteToGraphCallback seems like an even better approach than what I was speculating about in #6262 (comment).
I'd recommend we briefly explain that usage pattern in the Javadoc here though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is non-blocking, does that mean it can be called from multiple threads or from one thread only? This should be documented in the JavaDoc.
What prevent this from waiting on it self?
I was currious what would happen if you try waiting on your self? The Future#get does not say, but this small program hangs - never returns:
public static class A {
Future previous = null;
public static void main(String[] args) throws Exception {
var pool = Executors.newFixedThreadPool(5);
var a = new A();
var f = pool.submit(a::run);
a.previous = f;
}
void run() {
try {
Thread.sleep(500);
Thread.yield();
if (previous != null) {
System.err.println("Reference to it self obtained!");
previous.get();
System.err.println("Do not get here!");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}Output:
Reference to it self obtained!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@t2gran my understanding is that this method is intended to only be called in the runPolling() implementations of PollingGraphUpdater subclasses. Those are in turn only expected to be called by PollingGraphUpdater.run() which is in turn only run by GraphUpdaterManager.pollingUpdaterPool.scheduleWithFixedDelay() which, if I'm not mistaken, means it would only ever be called on one thread at a time.
So I think the self-waiting situation you describe should only arise if someone made a PollingGraphUpdater subclass, on which the runPolling method was implemented, written to contain something like updateGraph(self) instead of updateGraph(closure). Such intentional indirect recursion would imply the author was confused about how these updaters are meant to work. Would Javadoc clearly stating how this method is used in PollingGraphUpdaters be sufficient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What prevent this from waiting on it self?
There are 2 thread pools involved, one for the polling thread, one for the graph writer.
From the polling thread we wait for a task running in the graph writer thread, so I do not see a situation where "you wait on yourself"? Unless there is an implementation bug in the updater as @abyrd mentioned.
If this is non-blocking, does that mean it can be called from multiple threads or from one thread only? This should be documented in the JavaDoc.
Do you refer to an hypothetical PollingUpdater implementation that would itself be multi-threaded and that would call updateGraph() multiple times from several threads from its own thread pool?
No such updater exists today, but that would break the logic implemented in this PR, since this PR assumes that if a PollingUpdater calls updateGraph() multiple times, it does so sequentially.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a new change, but it still seems a bit odd to me that the interface and field have different names here, with the field name being a verb. There's also a comment below referring to this as the "GraphWriter" and I'm not sure anything still has that name. Probably all a result of a series of renamings as the callback interface was extracted from the update manager.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems the same field name "saveResultOnGraph" is used across all GraphUpdater implementations. I would keep this name for consistency for now. This can be refactored in a follow-up PR.