This is an automated email from the ASF dual-hosted git repository. frankgh pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/cassandra-sidecar.git
The following commit(s) were added to refs/heads/trunk by this push: new 1afdb68b CASSSIDECAR-178: Stopping Sidecar can take a long time (#162) 1afdb68b is described below commit 1afdb68bea7aef495a3cdc895b778fc4ea2c72e0 Author: Francisco Guerrero <fran...@apache.org> AuthorDate: Thu Dec 12 16:48:45 2024 -0800 CASSSIDECAR-178: Stopping Sidecar can take a long time (#162) Patch by Francisco Guerrero; Reviewed by Yifan Cai for CASSSIDECAR-178 --- CHANGES.txt | 1 + .../apache/cassandra/sidecar/server/Server.java | 43 ++++++++++++++++++---- .../cassandra/sidecar/server/ServerTest.java | 36 ++++++++++++++++++ 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 1c8d31a7..70cabce9 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,6 @@ 1.0.0 ----- + * Stopping Sidecar can take a long time (CASSSIDECAR-178) * Add support for operational job management of long-running node operations (CASSSIDECAR-150) * CDC directory not initialized properly in InstanceMetadata (CASSSIDECAR-171) * yaml configuration defaults to a file that doesn't exist (CASSSIDECAR-122) diff --git a/server/src/main/java/org/apache/cassandra/sidecar/server/Server.java b/server/src/main/java/org/apache/cassandra/sidecar/server/Server.java index 824c0e6e..15500bdb 100644 --- a/server/src/main/java/org/apache/cassandra/sidecar/server/Server.java +++ b/server/src/main/java/org/apache/cassandra/sidecar/server/Server.java @@ -46,6 +46,7 @@ import io.vertx.core.json.JsonObject; import io.vertx.core.net.SSLOptions; import io.vertx.core.net.TrafficShapingOptions; import io.vertx.ext.web.Router; +import org.apache.cassandra.sidecar.cluster.CassandraAdapterDelegate; import org.apache.cassandra.sidecar.cluster.InstancesConfig; import org.apache.cassandra.sidecar.cluster.instance.InstanceMetadata; import org.apache.cassandra.sidecar.common.utils.Preconditions; @@ -150,7 +151,7 @@ public class Server * * @return a future completed with the result */ - public Future<Void> close() + public Future<CompositeFuture> close() { LOGGER.info("Stopping Cassandra Sidecar"); deployedServerVerticles.clear(); @@ -161,13 +162,41 @@ public class Server periodicTaskExecutor.close(periodicTaskExecutorPromise); closingFutures.add(periodicTaskExecutorPromise.future()); - instancesConfig.instances() - .forEach(instance -> - closingFutures.add(executorPools.internal() - .runBlocking(() -> instance.delegate().close()))); + instancesConfig.instances().forEach(instance -> { + Promise<Void> closingFutureForInstance = Promise.promise(); + executorPools.internal() + .runBlocking(() -> { + try + { + CassandraAdapterDelegate delegate = instance.delegate(); + if (delegate != null) + { + delegate.close(); + } + } + catch (Exception e) + { + LOGGER.error("Failed to close delegate", e); + closingFutureForInstance.tryFail(e); + } + finally + { + closingFutureForInstance.tryComplete(null); + } + }); + closingFutures.add(closingFutureForInstance.future()); + }); + return Future.all(closingFutures) - .compose(v1 -> executorPools.close()) - .onComplete(v -> vertx.close()) + .andThen(v1 -> { + LOGGER.debug("Closing executor pools"); + executorPools.close(); + }) + .andThen(v -> { + LOGGER.debug("Closing vertx"); + vertx.close(); + }) + .onFailure(t -> LOGGER.error("Failed to gracefully shutdown Cassandra Sidecar", t)) .onSuccess(f -> LOGGER.info("Successfully stopped Cassandra Sidecar")); } diff --git a/server/src/test/java/org/apache/cassandra/sidecar/server/ServerTest.java b/server/src/test/java/org/apache/cassandra/sidecar/server/ServerTest.java index e294cd50..d4ec7012 100644 --- a/server/src/test/java/org/apache/cassandra/sidecar/server/ServerTest.java +++ b/server/src/test/java/org/apache/cassandra/sidecar/server/ServerTest.java @@ -210,6 +210,42 @@ class ServerTest }); } + @Test + @DisplayName("Server should stop immediately when there port is already in use") + void stopImmediatelyWhenPortIsInUse(VertxTestContext context) + { + long attemptStartTimeMillis = System.currentTimeMillis(); + server.start() + // simulate a bind exception due to address already in use + .compose(deploymentId -> Future.failedFuture(new java.net.BindException("Address already in use"))) + .onComplete(context.failing(result -> { + + try + { + server.close() + .toCompletionStage() + .toCompletableFuture() + .get(1, TimeUnit.MINUTES); + } + catch (Exception e) + { + context.failNow(e); + return; + } + + long elapsedTimeMillis = System.currentTimeMillis() - attemptStartTimeMillis; + if (elapsedTimeMillis < TimeUnit.SECONDS.toMillis(10)) + { + context.completeNow(); + } + else + { + context.failNow("Expected server close to take less than 10000 millis, " + + "but it took " + elapsedTimeMillis + " millis"); + } + })); + } + @Test @DisplayName("Update should fail with null options") void updatingTrafficShapingOptionsWithNull(VertxTestContext context) --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org