Bret McGuire created CASSANDRA-19468:
----------------------------------------
Summary: In some situations
MetadataManager.SingleThreaded.startSchemaRequest could fail to set
CompletableFuture arg
Key: CASSANDRA-19468
URL: https://issues.apache.org/jira/browse/CASSANDRA-19468
Project: Cassandra
Issue Type: Bug
Components: Client/java-driver
Reporter: Bret McGuire
Assignee: Henry Hughes
Relevant code is:
{code:java}
private void startSchemaRequest(CompletableFuture<RefreshSchemaResult>
refreshFuture) {
assert adminExecutor.inEventLoop();
if (closeWasCalled) {
refreshFuture.complete(new RefreshSchemaResult(metadata));
return;
}
if (currentSchemaRefresh == null) {
currentSchemaRefresh = refreshFuture;
LOG.debug("[{}] Starting schema refresh", logPrefix);
initControlConnectionForSchema()
.thenCompose(v -> context.getTopologyMonitor().checkSchemaAgreement())
.whenComplete(
(schemaInAgreement, agreementError) -> {
if (agreementError != null) {
refreshFuture.completeExceptionally(agreementError);
} else {
schemaQueriesFactory
.newInstance()
.execute()
.thenApplyAsync(this::parseAndApplySchemaRows,
adminExecutor)
.whenComplete(
(newMetadata, metadataError) -> {
if (metadataError != null) {
refreshFuture.completeExceptionally(metadataError);
} else {
refreshFuture.complete(
new RefreshSchemaResult(newMetadata,
schemaInAgreement));
}
...{code}
Problem is that the default impl of SchemaQueriesFactory
(DefaultSchemaQueriesFactory) can chuck exceptions in a few cases, most notably
if the control connection is in a bad way:
{code:java}
@Override
public SchemaQueries newInstance() {
DriverChannel channel = context.getControlConnection().channel();
if (channel == null || channel.closeFuture().isDone()) {
throw new IllegalStateException("Control channel not available, aborting
schema refresh");
}
Node node =
context
.getMetadataManager()
.getMetadata()
.findNode(channel.getEndPoint())
.orElseThrow(
() ->
new IllegalStateException(
"Could not find control node metadata "
+ channel.getEndPoint()
+ ", aborting schema refresh"));
return newInstance(node, channel);
} {code}
In this case the MetadataManager code above will exit out before it ever sets a
state on refreshFuture... meaning anything waiting on that future will just
continue to wait.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]