NoHostAvailableException during cassandraClient.connect leads to failure in Future.fail()
triplem opened this issue · 10 comments
try {
client = client.connect(CASSANDRA_KEYSPACE) { ar ->
if (ar.failed()) {
logger.error("ALL IS BAD....")
startFuture.fail(ar.cause())
} else {
repository = Repository(client)
vertx.eventBus().consumer<JsonObject>(ADDRESS, this::handle)
startFuture.complete()
}
}
} catch (e: Exception) {
logger.warn("catched exception")
startFuture.fail(e)
}
The above code leads to an exception, if no cassandra server is available (NoHostAvailableException). This exception is catched in the given catch block. If startFuture.complete() is called, all is fine (well, then the verticle is deployed, even though it shouldn't), but if startFuture.fail(e) is called, the event is not fetched in my MainVerticle.
Thanks for the fix, unfortunately this is still not working properly. The exception is catched and the future is failed, perfect. But in my MainVertical, I still do not get this state.
vertx.deployVerticle("ServiceVerticle") { ar ->
if (ar.failed()) {
logger.error("Could not start serviceVerticle", ar.cause())
} else {
logger.error("........................................")
logger.error("ar: ", ar.result())
}
}
In the above code, on an failed future, nothing really happens.
I not sure if I understood you correctly. Can you provide a reproducer in order to make it obvious?
My MainVertical deploys the ServiceVertical. The future is fine, if the ServiceVertical completes the future, but on a future.fail(cause), the AR in the MainVertical is not processed.
MainVertical#start:
vertx.deployVerticle("ServiceVerticle") { ar ->
if (ar.failed()) {
logger.error("Could not start serviceVerticle", ar.cause())
} else {
logger.error("........................................")
logger.error("ar: ", ar.result())
}
}
ServiceVertical#start(future):
client = client.connect(CASSANDRA_KEYSPACE) { ar ->
if (ar.failed()) {
logger.error("ALL IS BAD....")
if (client.isConnected) {
client.disconnect()
}
startFuture.fail(ar.cause())
} else {
repository = Repository(client)
vertx.eventBus().consumer<JsonObject>(ADDRESS, this::handle)
startFuture.complete()
}
}
If I do exchange startFuture.fail(ar.cause) with startFuture.complete() the result is propagated to the MainVertical, but not on a failed future.
Is this something, which can be fixed in Cassandra client? The future is failed by Cassandra client, so this is what is expected. If I got you right, the situation is similar to this:
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
public class Main {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new A());
}
static class A extends AbstractVerticle {
@Override
public void start() {
vertx.deployVerticle(new B(), deployResult -> {
if (deployResult.succeeded()) {
System.out.println("deployed");
} else {
System.out.println("not deployed, reason: " + deployResult.cause());
}
});
}
}
static class B extends AbstractVerticle {
@Override
public void start(Future<Void> startFuture) {
startFuture.fail("Something is wrong");
}
}
}
And not deployed, reason: ....
is printed in this case.
I have provided a "reproducer" in https://github.com/triplem/vertx-cassandra-client/tree/3.6 (take a look into the examples). But from your example above, this is exactly what is "NOT" happening.
@triplem , now I got what you mean. It seems that it is somehow connected with this line:
https://github.com/vert-x3/vertx-cassandra-client/blob/master/src/main/java/io/vertx/cassandra/impl/CassandraClientImpl.java#L51
Just created an issue for this: eclipse-vertx/vert.x#2809
Yes, this seems to solve this issue. I have applied it to my own 3.6 Branch, and it seems to work fine ;-) Thanks a lot for the quick reply and effort.