-
Notifications
You must be signed in to change notification settings - Fork 27
Improve waiting strategy for Integration tests - cont #409
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 |
---|---|---|
@@ -1,18 +1,24 @@ | ||
package com.redhat.parodos.sdkutils; | ||
|
||
import java.util.concurrent.Callable; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.ExecutionException; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.Future; | ||
import java.util.concurrent.ScheduledExecutorService; | ||
import java.util.concurrent.ScheduledFuture; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.TimeoutException; | ||
|
||
public class RetryExecutorService<T> implements AutoCloseable { | ||
|
||
private final ExecutorService executor; | ||
private static final int MAX_RETRY_TIME = 2 * 60 * 1000; // 2 minutes | ||
|
||
public static final int RETRY_DELAY = 5 * 1000; // 5 seconds | ||
|
||
private final ScheduledExecutorService scheduledExecutor; | ||
|
||
public RetryExecutorService() { | ||
executor = Executors.newFixedThreadPool(1); | ||
scheduledExecutor = Executors.newSingleThreadScheduledExecutor(); | ||
} | ||
|
||
/** | ||
|
@@ -22,7 +28,7 @@ public RetryExecutorService() { | |
*/ | ||
public T submitWithRetry(Callable<T> task) { | ||
// @formatter:off | ||
return submitWithRetry(task, () -> {}, () -> {}, 10 * 60 * 1000, 5000); | ||
return submitWithRetry(task, () -> {}, () -> {}, MAX_RETRY_TIME, RETRY_DELAY); | ||
// @formatter:on | ||
} | ||
|
||
|
@@ -37,48 +43,41 @@ public T submitWithRetry(Callable<T> task) { | |
*/ | ||
public T submitWithRetry(Callable<T> task, Runnable onSuccess, Runnable onFailure, long maxRetryTime, | ||
long retryDelay) { | ||
Future<T> future = executor.submit(() -> { | ||
long startTime = System.currentTimeMillis(); | ||
long endTime = startTime + maxRetryTime; | ||
|
||
while (System.currentTimeMillis() < endTime) { | ||
try { | ||
T result = task.call(); | ||
onSuccess.run(); | ||
return result; // Success, no need to retry | ||
} | ||
catch (Exception e) { | ||
// Task failed, invoke onFailure callback | ||
onFailure.run(); | ||
CompletableFuture<T> future = new CompletableFuture<>(); | ||
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. why is this future here needed? 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. it stores the result and is used as a reference to its success or failure. |
||
long startTime = System.currentTimeMillis(); | ||
long endTime = startTime + maxRetryTime; | ||
|
||
// Sleep for the retry delay | ||
try { | ||
// FIXME: This is a blocking call, we should use a non-blocking | ||
// sleep | ||
Thread.sleep(retryDelay); | ||
} | ||
catch (InterruptedException ex) { | ||
Thread.currentThread().interrupt(); | ||
return null; // Interrupted, exit the task | ||
} | ||
} | ||
ScheduledFuture<?> scheduledFuture = scheduledExecutor.scheduleWithFixedDelay(() -> { | ||
if (System.currentTimeMillis() >= endTime) { | ||
future.completeExceptionally(new TimeoutException("Retry limit reached.")); | ||
return; | ||
} | ||
Comment on lines
+51
to
54
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. Set a timeout in 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. No, setting a timeout using The |
||
|
||
return null; // Retry limit reached | ||
}); | ||
try { | ||
T result = task.call(); | ||
onSuccess.run(); | ||
future.complete(result); // Success, complete the future with the result | ||
} | ||
catch (Exception e) { | ||
onFailure.run(); | ||
} | ||
}, 0, retryDelay, TimeUnit.MILLISECONDS); | ||
|
||
try { | ||
return future.get(); | ||
} | ||
catch (InterruptedException | ExecutionException e) { | ||
throw new RuntimeException(e); | ||
} | ||
finally { | ||
scheduledFuture.cancel(false); | ||
scheduledExecutor.shutdown(); | ||
} | ||
} | ||
|
||
@Override | ||
public void close() throws Exception { | ||
executor.shutdown(); | ||
boolean awaited = executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); | ||
boolean awaited = scheduledExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); | ||
if (!awaited) { | ||
throw new RuntimeException("Failed to await termination of executor service"); | ||
} | ||
|
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.
I like this (and the commit message ;) )