Skip to content

Commit

Permalink
Fix Quarkus-cli flacky test on Quarkus start
Browse files Browse the repository at this point in the history
  • Loading branch information
pablo gonzalez granados committed Oct 28, 2021
1 parent 8cc2cf7 commit d91f325
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ public void shouldCreateApplicationWithCodeStarter() {
assertInstalledExtensions(app, RESTEASY_SPRING_WEB_EXTENSION);

// Start using DEV mode
app.start();
untilAsserted(() -> app.given().get("/greeting").then().statusCode(HttpStatus.SC_OK).and().body(is("Hello Spring")));
untilAsserted(() -> {
app.start();
app.given().get("/greeting").then().statusCode(HttpStatus.SC_OK).and().body(is("Hello Spring"));
});
}

@Test
Expand All @@ -100,17 +102,21 @@ public void shouldAddAndRemoveExtensions() {
assertInstalledExtensions(app, RESTEASY_EXTENSION, SMALLRYE_HEALTH_EXTENSION);

// The health endpoint should be now available
app.start();
untilAsserted(() -> app.given().get("/q/health").then().statusCode(HttpStatus.SC_OK));
untilAsserted(() -> {
app.start();
app.given().get("/q/health").then().statusCode(HttpStatus.SC_OK);
});
app.stop();

// Let's now remove the Smallrye Health extension
result = app.removeExtension(SMALLRYE_HEALTH_EXTENSION);
assertTrue(result.isSuccessful(), SMALLRYE_HEALTH_EXTENSION + " was not uninstalled. Output: " + result.getOutput());

// The health endpoint should be now gone
app.start();
untilAsserted(() -> app.given().get("/q/health").then().statusCode(HttpStatus.SC_NOT_FOUND));
untilAsserted(() -> {
app.start();
app.given().get("/q/health").then().statusCode(HttpStatus.SC_NOT_FOUND);
});
}

private void assertInstalledExtensions(QuarkusCliRestService app, String... expectedExtensions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

Expand All @@ -32,6 +35,7 @@ public class BaseService<T extends Service> implements Service {

private static final String SERVICE_STARTUP_CHECK_POLL_INTERVAL = "startup.check-poll-interval";
private static final Duration SERVICE_STARTUP_CHECK_POLL_INTERVAL_DEFAULT = Duration.ofSeconds(2);
private static final int MAX_RETRIES = 3;

private final ServiceLoader<ServiceListener> listeners = ServiceLoader.load(ServiceListener.class);

Expand Down Expand Up @@ -177,16 +181,15 @@ public String getProperty(String property, String defaultValue) {
*/
@Override
public void start() {
if (isRunning()) {
return;
try {
CompletableFuture
.runAsync(() -> startExec())
.thenApply(CompletableFuture::completedFuture)
.exceptionally(t -> retry(t, 0))
.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}

Log.debug(this, "Starting service (%s)", getDisplayName());
onPreStartActions.forEach(a -> a.handle(this));
doStart();
waitUntilServiceIsStarted();
onPostStartActions.forEach(a -> a.handle(this));
Log.info(this, "Service started (%s)", getDisplayName());
}

/**
Expand Down Expand Up @@ -289,4 +292,31 @@ private void waitUntilServiceIsStarted() {
.withService(this)
.timeoutMessage("Service didn't start in %s minutes", startupTimeout));
}

private CompletableFuture<Void> startExec() {
CompletableFuture<Void> result = CompletableFuture.completedFuture(null);
if (isRunning()) {
return result;
}
Log.debug(this, "Starting service (%s)", getDisplayName());
onPreStartActions.forEach(a -> a.handle(this));
doStart();
waitUntilServiceIsStarted();
onPostStartActions.forEach(a -> a.handle(this));
Log.info(this, "Service started (%s)", getDisplayName());
return result;
}

private CompletableFuture<Void> retry(Throwable ex, int retry) {
if (retry >= MAX_RETRIES) {
throw new RuntimeException(ex);
}

return startExec()
.thenApply(CompletableFuture::completedFuture)
.exceptionally(error -> {
ex.addSuppressed(error);
return retry(ex, retry + 1);
}).thenCompose(Function.identity());
}
}

0 comments on commit d91f325

Please sign in to comment.