-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Conditionally wait for previous polling task #6401
base: dev-2.x
Are you sure you want to change the base?
Changes from all commits
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. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think the expression "handle on" is idiomatic, particularly without an article. It might be mistaken for an imperative verb. I suggest we adapt the language in ExecutorService.submit Javadoc: "a Future representing pending completion of the task".
Suggested change
|
||||||
* If the updater posts several tasks during one polling cycle, the handle will point to the | ||||||
* latest posted task. | ||||||
* Initially null when the polling updater starts. | ||||||
*/ | ||||||
private Future<?> previousTask; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add @nullable here. |
||||||
|
||||||
/** Shared configuration code for all polling graph updaters. */ | ||||||
protected PollingGraphUpdater(PollingGraphUpdaterParameters config) { | ||||||
|
@@ -55,6 +64,10 @@ public Duration pollingPeriod() { | |||||
@Override | ||||||
public final void run() { | ||||||
try { | ||||||
if (OTPFeature.WaitForGraphUpdateInPollingUpdaters.isOn()) { | ||||||
waitForPreviousTask(); | ||||||
} | ||||||
|
||||||
// Run concrete polling graph updater's implementation method. | ||||||
runPolling(); | ||||||
if (runOnlyOnce()) { | ||||||
|
@@ -113,11 +126,30 @@ public final void setup(WriteToGraphCallback writeToGraphCallback) { | |||||
*/ | ||||||
protected abstract void runPolling() throws Exception; | ||||||
|
||||||
protected final void updateGraph(GraphWriterRunnable task) | ||||||
throws ExecutionException, InterruptedException { | ||||||
var result = saveResultOnGraph.execute(task); | ||||||
if (OTPFeature.WaitForGraphUpdateInPollingUpdaters.isOn()) { | ||||||
result.get(); | ||||||
/** | ||||||
* Post an update task to the GraphWriter queue. | ||||||
* This is non-blocking. | ||||||
* This can be called several times during one polling cycle. | ||||||
*/ | ||||||
protected final void updateGraph(GraphWriterRunnable task) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The system in this PR where this method is called from |
||||||
previousTask = saveResultOnGraph.execute(task); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is What prevent this from waiting on it self? I was currious what would happen if you try waiting on your self? The 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:
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 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 |
||||||
} | ||||||
|
||||||
/** | ||||||
* If the previous task takes longer than the polling interval, | ||||||
* we delay the next polling cycle until the task is complete. | ||||||
* This prevents tasks from piling up. | ||||||
* If the updater sends several tasks during a polling cycle, we wait on the latest posted task. | ||||||
* */ | ||||||
private void waitForPreviousTask() throws InterruptedException, ExecutionException { | ||||||
if (previousTask != null && !previousTask.isDone()) { | ||||||
LOG.info("Delaying polling until the previous task is complete"); | ||||||
long startBlockingWait = System.currentTimeMillis(); | ||||||
previousTask.get(); | ||||||
LOG.info( | ||||||
"Resuming polling after waiting an additional {}s", | ||||||
(System.currentTimeMillis() - startBlockingWait) / 1000 | ||||||
); | ||||||
} | ||||||
} | ||||||
} |
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.