This is an automated email from the ASF dual-hosted git repository.
korlov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new e4a495634b IGNITE-17685 Sql. SQL engine should send messages
asynchronously (#1980)
e4a495634b is described below
commit e4a495634ba7865f4e8a982f24d1783f65850dbd
Author: korlov42 <[email protected]>
AuthorDate: Thu Apr 27 09:20:53 2023 +0300
IGNITE-17685 Sql. SQL engine should send messages asynchronously (#1980)
---
.../java/org/apache/ignite/lang/ErrorGroups.java | 6 +-
.../apache/ignite/internal/sql/engine/Stubs.java | 25 ---
.../internal/sql/engine/exec/ExchangeService.java | 98 +++++------
.../sql/engine/exec/ExchangeServiceImpl.java | 68 ++------
.../sql/engine/exec/ExecutionServiceImpl.java | 192 +++++++++++++--------
.../internal/sql/engine/exec/MailboxRegistry.java | 12 --
.../sql/engine/exec/MailboxRegistryImpl.java | 31 ----
.../ignite/internal/sql/engine/exec/rel/Inbox.java | 29 ++--
.../internal/sql/engine/exec/rel/Outbox.java | 65 +++++--
.../sql/engine/message/InboxCloseMessage.java | 45 -----
.../sql/engine/message/MessageService.java | 12 +-
.../sql/engine/message/MessageServiceImpl.java | 31 ++--
.../sql/engine/message/SqlQueryMessageGroup.java | 4 +-
.../ignite/internal/sql/engine/prepare/Cloner.java | 2 +-
.../internal/sql/engine/prepare/FragmentPlan.java | 65 -------
.../internal/sql/engine/StopCalciteModuleTest.java | 1 -
.../sql/engine/exec/ExecutionServiceImplTest.java | 58 +++----
.../internal/sql/engine/framework/TestNode.java | 1 -
18 files changed, 272 insertions(+), 473 deletions(-)
diff --git a/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
b/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
index 7ddb303ad3..2fd6edc2fb 100755
--- a/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
+++ b/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
@@ -187,9 +187,6 @@ public class ErrorGroups {
/** Node left the cluster. */
public static final int NODE_LEFT_ERR =
SQL_ERR_GROUP.registerErrorCode(27);
- /** Message send error. */
- public static final int MESSAGE_SEND_ERR =
SQL_ERR_GROUP.registerErrorCode(28);
-
/** Operation aborted/interrupted error. */
public static final int OPERATION_INTERRUPTED_ERR =
SQL_ERR_GROUP.registerErrorCode(29);
@@ -204,6 +201,9 @@ public class ErrorGroups {
/** Execution cancelled. */
public static final int EXECUTION_CANCELLED_ERR =
SQL_ERR_GROUP.registerErrorCode(33);
+
+ /** Error code describing any unexpected situation. */
+ public static final int INTERNAL_ERR =
SQL_ERR_GROUP.registerErrorCode(34);
}
/** Meta storage error group. */
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/Stubs.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/Stubs.java
deleted file mode 100644
index e83bb5785e..0000000000
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/Stubs.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.sql.engine;
-
-/** Stubs. */
-public class Stubs {
- public static int intFoo(Object... args) {
- return args == null ? 0 : args.length;
- }
-}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExchangeService.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExchangeService.java
index acd62415a0..e038afd632 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExchangeService.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExchangeService.java
@@ -19,77 +19,61 @@ package org.apache.ignite.internal.sql.engine.exec;
import java.util.List;
import java.util.UUID;
-import org.apache.ignite.lang.IgniteInternalCheckedException;
+import java.util.concurrent.CompletableFuture;
+import org.apache.ignite.internal.sql.engine.exec.rel.Inbox;
+import org.apache.ignite.internal.sql.engine.exec.rel.Outbox;
import org.jetbrains.annotations.Nullable;
/**
- * ExchangeService interface.
- * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
+ * The interface describes a minimal but sufficient set of methods to make
+ * the exchange of information between mailboxes work.
+ *
+ * @see MailboxRegistry
+ * @see Outbox
+ * @see Inbox
*/
public interface ExchangeService extends LifecycleAware {
/**
- * Sends a batch of data to remote node.
- *
- * @param nodeName Target node consistent ID.
- * @param qryId Query ID.
- * @param fragmentId Target fragment ID.
- * @param exchangeId Exchange ID.
- * @param batchId Batch ID.
- * @param last Last batch flag.
- * @param rows Data rows.
- */
- <RowT> void sendBatch(String nodeName, UUID qryId, long fragmentId, long
exchangeId, int batchId, boolean last,
- List<RowT> rows) throws IgniteInternalCheckedException;
-
- /**
- * Requests batches from remote source.
- *
- * @param nodeName A consistent identifier of the node to request from.
- * @param queryId An identifier of the query.
- * @param fragmentId An identifier of the fragment to request from.
- * @param exchangeId An identifier of the exchange to request from.
- * @param amountOfBatches A count of batches to request.
- * @param state A state to propagate to the remote source.
- */
- void request(String nodeName, UUID queryId, long fragmentId, long
exchangeId, int amountOfBatches,
- @Nullable SharedState state) throws IgniteInternalCheckedException;
-
- /**
- * Sends cancel request.
- *
- * @param nodeName Target node consistent ID.
- * @param qryId Query ID.
- * @param fragmentId Target fragment ID.
- * @param exchangeId Exchange ID.
- */
- void closeInbox(String nodeName, UUID qryId, long fragmentId, long
exchangeId) throws IgniteInternalCheckedException;
-
- /**
- * Sends cancel request.
+ * Asynchronously sends a batch of data to the specified node.
*
- * @param nodeName Target node consistent ID.
- * @param qryId Query ID.
+ * @param nodeName The name of the node to which the data will be sent.
+ * @param queryId The ID of the query to which the data belongs.
+ * @param fragmentId The ID of the fragment to which the data will be sent.
+ * @param exchangeId The ID of the exchange through which the data will be
sent.
+ * @param batchId The ID of the batch to which the data belongs.
+ * @param last Indicates whether this is the last batch of data to be sent.
+ * @param rows The data to be sent.
+ * @param <RowT> The type of the rows int the batch.
+ * @return A {@link CompletableFuture future} representing the result of
operation,
+ * which completes when the data has been sent.
*/
- void closeQuery(String nodeName, UUID qryId) throws
IgniteInternalCheckedException;
+ <RowT> CompletableFuture<Void> sendBatch(String nodeName, UUID queryId,
long fragmentId, long exchangeId, int batchId, boolean last,
+ List<RowT> rows);
/**
- * Send error.
- * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
+ * Asynchronously requests data from the specified node.
*
- * @param nodeName Target node consistent ID.
- * @param qryId Query ID.
- * @param fragmentId Source fragment ID.
- * @param err Exception to send.
- * @throws IgniteInternalCheckedException On error marshaling or send
ErrorMessage.
+ * @param nodeName The name of the node from which the data will be
requested.
+ * @param queryId The ID of the query for which the data is being
requested.
+ * @param fragmentId The ID of the fragment from which the data will be
requested.
+ * @param exchangeId The ID of the exchange through which the data will be
requested.
+ * @param amountOfBatches The number of batches of data to request.
+ * @param state The state to propagate to the remote node, or null if
state is not changed or not required.
+ * @return A {@link CompletableFuture future} representing the result of
operation,
+ * which completes when the request message has been sent.
*/
- void sendError(String nodeName, UUID qryId, long fragmentId, Throwable
err) throws IgniteInternalCheckedException;
+ CompletableFuture<Void> request(String nodeName, UUID queryId, long
fragmentId, long exchangeId, int amountOfBatches,
+ @Nullable SharedState state);
/**
- * Alive.
- * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
+ * Asynchronously sends an error message to the specified node.
*
- * @param nodeName Target node consistent ID.
- * @return {@code true} if node is alive, {@code false} otherwise.
+ * @param nodeName The name of the node to which the error will be sent.
+ * @param queryId The ID of the query to which the error belongs.
+ * @param fragmentId The ID of the fragment to which the error belongs.
+ * @param error The error to send.
+ * @return A {@link CompletableFuture future} representing the result of
operation,
+ * which completes when the error message has been sent.
*/
- boolean alive(String nodeName);
+ CompletableFuture<Void> sendError(String nodeName, UUID queryId, long
fragmentId, Throwable error);
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExchangeServiceImpl.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExchangeServiceImpl.java
index e83a2b2ae1..a25cc6bfe9 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExchangeServiceImpl.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExchangeServiceImpl.java
@@ -17,10 +17,8 @@
package org.apache.ignite.internal.sql.engine.exec;
-import static org.apache.ignite.internal.util.CollectionUtils.nullOrEmpty;
import static org.apache.ignite.lang.ErrorGroups.Common.UNEXPECTED_ERR;
-import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@@ -29,14 +27,12 @@ import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.sql.engine.exec.rel.Inbox;
import org.apache.ignite.internal.sql.engine.exec.rel.Outbox;
-import org.apache.ignite.internal.sql.engine.message.InboxCloseMessage;
import org.apache.ignite.internal.sql.engine.message.MessageService;
import org.apache.ignite.internal.sql.engine.message.QueryBatchMessage;
import org.apache.ignite.internal.sql.engine.message.QueryBatchRequestMessage;
import org.apache.ignite.internal.sql.engine.message.SqlQueryMessageGroup;
import org.apache.ignite.internal.sql.engine.message.SqlQueryMessagesFactory;
import org.apache.ignite.internal.sql.engine.util.Commons;
-import org.apache.ignite.lang.IgniteInternalCheckedException;
import org.apache.ignite.lang.IgniteInternalException;
import org.jetbrains.annotations.Nullable;
@@ -69,16 +65,15 @@ public class ExchangeServiceImpl implements ExchangeService
{
/** {@inheritDoc} */
@Override
public void start() {
- messageService.register((n, m) -> onMessage(n, (InboxCloseMessage) m),
SqlQueryMessageGroup.INBOX_CLOSE_MESSAGE);
messageService.register((n, m) -> onMessage(n,
(QueryBatchRequestMessage) m), SqlQueryMessageGroup.QUERY_BATCH_REQUEST);
messageService.register((n, m) -> onMessage(n, (QueryBatchMessage) m),
SqlQueryMessageGroup.QUERY_BATCH_MESSAGE);
}
/** {@inheritDoc} */
@Override
- public <RowT> void sendBatch(String nodeName, UUID qryId, long fragmentId,
long exchangeId, int batchId,
- boolean last, List<RowT> rows) throws
IgniteInternalCheckedException {
- messageService.send(
+ public <RowT> CompletableFuture<Void> sendBatch(String nodeName, UUID
qryId, long fragmentId, long exchangeId, int batchId,
+ boolean last, List<RowT> rows) {
+ return messageService.send(
nodeName,
FACTORY.queryBatchMessage()
.queryId(qryId)
@@ -93,9 +88,9 @@ public class ExchangeServiceImpl implements ExchangeService {
/** {@inheritDoc} */
@Override
- public void request(String nodeName, UUID queryId, long fragmentId, long
exchangeId, int amountOfBatches,
- @Nullable SharedState state) throws IgniteInternalCheckedException
{
- messageService.send(
+ public CompletableFuture<Void> request(String nodeName, UUID queryId, long
fragmentId, long exchangeId, int amountOfBatches,
+ @Nullable SharedState state) {
+ return messageService.send(
nodeName,
FACTORY.queryBatchRequestMessage()
.queryId(queryId)
@@ -109,60 +104,17 @@ public class ExchangeServiceImpl implements
ExchangeService {
/** {@inheritDoc} */
@Override
- public void closeQuery(String nodeName, UUID qryId) throws
IgniteInternalCheckedException {
- messageService.send(
- nodeName,
- FACTORY.queryCloseMessage()
- .queryId(qryId)
- .build()
- );
- }
-
- /** {@inheritDoc} */
- @Override
- public void closeInbox(String nodeName, UUID qryId, long fragmentId, long
exchangeId) throws IgniteInternalCheckedException {
- messageService.send(
- nodeName,
- FACTORY.inboxCloseMessage()
- .queryId(qryId)
- .fragmentId(fragmentId)
- .exchangeId(exchangeId)
- .build()
- );
- }
-
- /** {@inheritDoc} */
- @Override
- public void sendError(String nodeName, UUID qryId, long fragmentId,
Throwable err) throws IgniteInternalCheckedException {
- messageService.send(
+ public CompletableFuture<Void> sendError(String nodeName, UUID queryId,
long fragmentId, Throwable error) {
+ return messageService.send(
nodeName,
FACTORY.errorMessage()
- .queryId(qryId)
+ .queryId(queryId)
.fragmentId(fragmentId)
- .error(err)
+ .error(error)
.build()
);
}
- /** {@inheritDoc} */
- @Override
- public boolean alive(String nodeName) {
- return messageService.alive(nodeName);
- }
-
- private void onMessage(String nodeName, InboxCloseMessage msg) {
- Collection<Inbox<?>> inboxes = mailboxRegistry.inboxes(msg.queryId(),
msg.fragmentId(), msg.exchangeId());
-
- if (!nullOrEmpty(inboxes)) {
- for (Inbox<?> inbox : inboxes) {
- inbox.context().execute(inbox::close, inbox::onError);
- }
- } else if (LOG.isDebugEnabled()) {
- LOG.debug("Stale inbox cancel message received [nodeName={},
queryId={}, fragmentId={}, exchangeId={}]",
- nodeName, msg.queryId(), msg.fragmentId(),
msg.exchangeId());
- }
- }
-
private void onMessage(String nodeName, QueryBatchRequestMessage msg) {
CompletableFuture<Outbox<?>> outboxFut =
mailboxRegistry.outbox(msg.queryId(), msg.exchangeId());
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
index 4df81cce82..76c2404894 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
@@ -21,8 +21,8 @@ import static
org.apache.ignite.internal.sql.engine.externalize.RelJsonReader.fr
import static
org.apache.ignite.internal.sql.engine.util.Commons.FRAMEWORK_CONFIG;
import static org.apache.ignite.internal.util.CollectionUtils.nullOrEmpty;
import static org.apache.ignite.lang.ErrorGroups.Sql.DDL_EXEC_ERR;
-import static org.apache.ignite.lang.ErrorGroups.Sql.MESSAGE_SEND_ERR;
import static org.apache.ignite.lang.ErrorGroups.Sql.NODE_LEFT_ERR;
+import static org.apache.ignite.lang.IgniteStringFormatter.format;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.ArrayList;
@@ -63,10 +63,10 @@ import
org.apache.ignite.internal.sql.engine.metadata.MappingService;
import org.apache.ignite.internal.sql.engine.metadata.MappingServiceImpl;
import org.apache.ignite.internal.sql.engine.metadata.NodeWithTerm;
import org.apache.ignite.internal.sql.engine.metadata.RemoteException;
+import org.apache.ignite.internal.sql.engine.prepare.Cloner;
import org.apache.ignite.internal.sql.engine.prepare.DdlPlan;
import org.apache.ignite.internal.sql.engine.prepare.ExplainPlan;
import org.apache.ignite.internal.sql.engine.prepare.Fragment;
-import org.apache.ignite.internal.sql.engine.prepare.FragmentPlan;
import org.apache.ignite.internal.sql.engine.prepare.IgniteRelShuttle;
import org.apache.ignite.internal.sql.engine.prepare.MappingQueryContext;
import org.apache.ignite.internal.sql.engine.prepare.MultiStepPlan;
@@ -84,6 +84,8 @@ import
org.apache.ignite.internal.sql.engine.util.HashFunctionFactoryImpl;
import org.apache.ignite.internal.sql.engine.util.TypeUtils;
import
org.apache.ignite.internal.table.distributed.replicator.TablePartitionId;
import org.apache.ignite.internal.tx.InternalTransaction;
+import org.apache.ignite.internal.util.ExceptionUtils;
+import org.apache.ignite.lang.ErrorGroups.Sql;
import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.lang.IgniteInternalCheckedException;
import org.apache.ignite.lang.IgniteInternalException;
@@ -108,7 +110,7 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
private static final SqlQueryMessagesFactory FACTORY = new
SqlQueryMessagesFactory();
- private final MessageService msgSrvc;
+ private final MessageService messageService;
private final TopologyService topSrvc;
@@ -120,8 +122,6 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
private final MappingService mappingSrvc;
- private final ExchangeService exchangeSrvc;
-
private final RowHandler<RowT> handler;
private final DdlCommandHandler ddlCmdHnd;
@@ -162,7 +162,6 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
ddlCommandHandler,
taskExecutor,
handler,
- exchangeSrvc,
ctx -> new LogicalRelImplementor<>(
ctx,
new HashFunctionFactoryImpl<>(sqlSchemaManager,
handler),
@@ -175,35 +174,32 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
/**
* Constructor.
*
- * @param msgSrvc Message service.
+ * @param messageService Message service.
* @param topSrvc Topology service.
* @param mappingSrvc Nodes mapping calculation service.
* @param sqlSchemaManager Schema manager.
* @param ddlCmdHnd Handler of the DDL commands.
* @param taskExecutor Task executor.
* @param handler Row handler.
- * @param exchangeSrvc Exchange service.
* @param implementorFactory Relational node implementor factory.
*/
public ExecutionServiceImpl(
- MessageService msgSrvc,
+ MessageService messageService,
TopologyService topSrvc,
MappingService mappingSrvc,
SqlSchemaManager sqlSchemaManager,
DdlCommandHandler ddlCmdHnd,
QueryTaskExecutor taskExecutor,
RowHandler<RowT> handler,
- ExchangeService exchangeSrvc,
ImplementorFactory<RowT> implementorFactory
) {
this.localNode = topSrvc.localMember();
this.handler = handler;
- this.msgSrvc = msgSrvc;
+ this.messageService = messageService;
this.mappingSrvc = mappingSrvc;
this.topSrvc = topSrvc;
this.sqlSchemaManager = sqlSchemaManager;
this.taskExecutor = taskExecutor;
- this.exchangeSrvc = exchangeSrvc;
this.ddlCmdHnd = ddlCmdHnd;
this.implementorFactory = implementorFactory;
}
@@ -211,10 +207,10 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
/** {@inheritDoc} */
@Override
public void start() {
- msgSrvc.register((n, m) -> onMessage(n, (QueryStartRequest) m),
SqlQueryMessageGroup.QUERY_START_REQUEST);
- msgSrvc.register((n, m) -> onMessage(n, (QueryStartResponse) m),
SqlQueryMessageGroup.QUERY_START_RESPONSE);
- msgSrvc.register((n, m) -> onMessage(n, (QueryCloseMessage) m),
SqlQueryMessageGroup.QUERY_CLOSE_MESSAGE);
- msgSrvc.register((n, m) -> onMessage(n, (ErrorMessage) m),
SqlQueryMessageGroup.ERROR_MESSAGE);
+ messageService.register((n, m) -> onMessage(n, (QueryStartRequest) m),
SqlQueryMessageGroup.QUERY_START_REQUEST);
+ messageService.register((n, m) -> onMessage(n, (QueryStartResponse)
m), SqlQueryMessageGroup.QUERY_START_RESPONSE);
+ messageService.register((n, m) -> onMessage(n, (QueryCloseMessage) m),
SqlQueryMessageGroup.QUERY_CLOSE_MESSAGE);
+ messageService.register((n, m) -> onMessage(n, (ErrorMessage) m),
SqlQueryMessageGroup.ERROR_MESSAGE);
}
private AsyncCursor<List<Object>> executeQuery(
@@ -246,10 +242,10 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
.build();
}
- private QueryPlan prepareFragment(String jsonFragment, BaseQueryContext
ctx) {
+ private IgniteRel relationalTreeFromJsonString(String jsonFragment,
BaseQueryContext ctx) {
IgniteRel plan = physNodesCache.computeIfAbsent(jsonFragment, ser ->
fromJson(ctx, ser));
- return new FragmentPlan(plan);
+ return new Cloner(Commons.cluster()).visit(plan);
}
/** {@inheritDoc} */
@@ -383,12 +379,6 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
f.join();
}
- /** {@inheritDoc} */
- @Override
- public void onAppeared(ClusterNode member) {
- // NO_OP
- }
-
/** {@inheritDoc} */
@Override
public void onDisappeared(ClusterNode member) {
@@ -419,19 +409,17 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
}
private DistributedQueryManager getOrCreateQueryManager(QueryStartRequest
msg) {
- DistributedQueryManager queryManager =
queryManagerMap.computeIfAbsent(msg.queryId(), key -> {
+ return queryManagerMap.computeIfAbsent(msg.queryId(), key -> {
BaseQueryContext ctx = createQueryContext(key, msg.schema(),
msg.parameters());
return new DistributedQueryManager(ctx);
});
-
- return queryManager;
}
/**
* A convenient class that manages the initialization and termination of
distributed queries.
*/
- class DistributedQueryManager {
+ private class DistributedQueryManager {
private final BaseQueryContext ctx;
private final CompletableFuture<Void> cancelFut = new
CompletableFuture<>();
@@ -465,10 +453,10 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
return List.copyOf(localFragments);
}
- private void sendFragment(
+ private CompletableFuture<Void> sendFragment(
String targetNodeName, Fragment fragment, FragmentDescription
desc, TxAttributes txAttributes
- ) throws IgniteInternalCheckedException {
- QueryStartRequest req = FACTORY.queryStartRequest()
+ ) {
+ QueryStartRequest request = FACTORY.queryStartRequest()
.queryId(ctx.queryId())
.fragmentId(fragment.fragmentId())
.schema(ctx.schemaName())
@@ -479,16 +467,14 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
.schemaVersion(ctx.schemaVersion())
.build();
- var fut = new CompletableFuture<Void>();
- remoteFragmentInitCompletion.put(new
RemoteFragmentKey(targetNodeName, fragment.fragmentId()), fut);
+ CompletableFuture<Void>
remoteFragmentInitializationCompletionFuture = new CompletableFuture<>();
- try {
- msgSrvc.send(targetNodeName, req);
- } catch (Exception ex) {
- fut.complete(null);
+ remoteFragmentInitCompletion.put(
+ new RemoteFragmentKey(targetNodeName,
fragment.fragmentId()),
+ remoteFragmentInitializationCompletionFuture
+ );
- throw ex;
- }
+ return messageService.send(targetNodeName, request);
}
private void acknowledgeFragment(String nodeName, long fragmentId,
@Nullable Throwable ex) {
@@ -525,15 +511,15 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
NODE_LEFT_ERR, "Node left the cluster
[nodeName=" + nodeName + "]")));
}
- private void executeFragment(FragmentPlan plan, ExecutionContext<RowT>
ectx) {
+ private CompletableFuture<Void> executeFragment(IgniteRel treeRoot,
ExecutionContext<RowT> ectx) {
String origNodeName = ectx.originatingNodeName();
- AbstractNode<RowT> node =
implementorFactory.create(ectx).go(plan.root());
+ AbstractNode<RowT> node =
implementorFactory.create(ectx).go(treeRoot);
localFragments.add(node);
if (!(node instanceof Outbox)) {
- Function<RowT, RowT> internalTypeConverter =
TypeUtils.resultTypeConverter(ectx, plan.root().getRowType());
+ Function<RowT, RowT> internalTypeConverter =
TypeUtils.resultTypeConverter(ectx, treeRoot.getRowType());
AsyncRootNode<RowT, List<Object>> rootNode = new
AsyncRootNode<>(node, inRow -> {
inRow = internalTypeConverter.apply(inRow);
@@ -555,21 +541,19 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
root.complete(rootNode);
}
- try {
- msgSrvc.send(
- origNodeName,
- FACTORY.queryStartResponse()
- .queryId(ectx.queryId())
- .fragmentId(ectx.fragmentId())
- .build()
- );
- } catch (IgniteInternalCheckedException e) {
- throw new IgniteInternalException(MESSAGE_SEND_ERR, "Failed to
send reply. [nodeName=" + origNodeName + ']', e);
- }
+ CompletableFuture<Void> sendingResult = messageService.send(
+ origNodeName,
+ FACTORY.queryStartResponse()
+ .queryId(ectx.queryId())
+ .fragmentId(ectx.fragmentId())
+ .build()
+ );
if (node instanceof Outbox) {
((Outbox<?>) node).prefetch();
}
+
+ return sendingResult;
}
private ExecutionContext<RowT> createContext(String initiatorNodeName,
FragmentDescription desc, TxAttributes txAttributes) {
@@ -592,22 +576,26 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
FragmentDescription desc,
TxAttributes txAttributes
) {
- try {
- QueryPlan qryPlan = prepareFragment(fragmentString, ctx);
+ CompletableFuture<?> start = new CompletableFuture<>();
- FragmentPlan plan = (FragmentPlan) qryPlan;
+ start.thenCompose(none -> {
+ IgniteRel treeRoot =
relationalTreeFromJsonString(fragmentString, ctx);
- executeFragment(plan, createContext(initiatorNode, desc,
txAttributes));
- } catch (Throwable ex) {
+ return executeFragment(treeRoot, createContext(initiatorNode,
desc, txAttributes));
+ }).exceptionally(ex -> {
handleError(ex, initiatorNode, desc.fragmentId());
- }
+
+ return null;
+ });
+
+ start.complete(null);
}
private void handleError(Throwable ex, String initiatorNode, long
fragmentId) {
LOG.debug("Unable to start query fragment", ex);
try {
- msgSrvc.send(
+ messageService.send(
initiatorNode,
FACTORY.queryStartResponse()
.queryId(ctx.queryId())
@@ -644,6 +632,8 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
// of the commit partition (if there is at least one table
in the fragments)
TxAttributes attributes = TxAttributes.fromTx(tx);
+ List<CompletableFuture<?>> resultsOfFragmentSending = new
ArrayList<>();
+
// start remote execution
for (Fragment fragment : fragments) {
if (fragment.rootFragment()) {
@@ -661,10 +651,68 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
);
for (String nodeName : fragmentDesc.nodeNames()) {
- sendFragment(nodeName, fragment, fragmentDesc,
attributes);
+ CompletableFuture<Void> resultOfSending =
sendFragment(nodeName, fragment, fragmentDesc, attributes);
+
+ resultsOfFragmentSending.add(resultOfSending);
+
+ resultOfSending.handle((ignored, t) -> {
+ if (t == null) {
+ return null;
+ }
+
+ // if we were unable to send a request, then
no need
+ // to wait for the remote node to complete
initialization
+
+ CompletableFuture<?> completionFuture =
remoteFragmentInitCompletion.get(
+ new RemoteFragmentKey(nodeName,
fragment.fragmentId())
+ );
+
+ if (completionFuture != null) {
+ completionFuture.complete(null);
+ }
+
+ throw ExceptionUtils.withCauseAndCode(
+ IgniteInternalException::new,
+ Sql.INTERNAL_ERR,
+ format("Unable to send fragment
[targetNode={}, fragmentId={}, cause={}]",
+ nodeName,
fragment.fragmentId(), t.getMessage()),
+ t
+ );
+ });
}
}
+
+
CompletableFuture.allOf(resultsOfFragmentSending.toArray(new
CompletableFuture[0]))
+ .handle((ignoredVal, ignoredTh) -> {
+ if (ignoredTh == null) {
+ return null;
+ }
+
+ Throwable firstFoundError = null;
+
+ for (CompletableFuture<?> fut :
resultsOfFragmentSending) {
+ if (fut.isCompletedExceptionally()) {
+ // this is non blocking join() because
we are inside of CompletableFuture.allOf call
+ Throwable fromFuture =
fut.handle((ignored, ex) -> ex).join();
+
+ if (firstFoundError == null) {
+ firstFoundError = fromFuture;
+ } else {
+
firstFoundError.addSuppressed(fromFuture);
+ }
+ }
+ }
+
+ Throwable error = firstFoundError;
+ if (!root.completeExceptionally(error)) {
+ root.thenAccept(root ->
root.onError(error));
+ }
+
+ return null;
+ });
} catch (Throwable t) {
+ LOG.warn("Unexpected exception during query
initialization", t);
+
if (!root.completeExceptionally(t)) {
root.thenAccept(root -> root.onError(t));
}
@@ -766,24 +814,22 @@ public class ExecutionServiceImpl<RowT> implements
ExecutionService, TopologyEve
for (Map.Entry<String, List<CompletableFuture<?>>>
entry : requestsPerNode.entrySet()) {
String nodeId = entry.getKey();
- if (!exchangeSrvc.alive(nodeId)) {
- continue;
- }
-
cancelFuts.add(
CompletableFuture.allOf(entry.getValue().toArray(new CompletableFuture[0]))
.handle((none2, t) -> {
- // t is ignored in this block
because it's passed to a cursor.
-
- try {
-
exchangeSrvc.closeQuery(nodeId, ctx.queryId());
- } catch
(IgniteInternalCheckedException e) {
- throw new
IgniteInternalException(MESSAGE_SEND_ERR,
- "Failed to send
cancel message. [nodeId=" + nodeId + ']', e);
- }
+ // Some fragments may be
completed exceptionally, and that is fine.
+ // Here we need to make sure
that all query initialisation requests
+ // have been processed before
sending a cancellation request. That's
+ // why we just ignore any
exception.
return null;
})
+ .thenCompose(ignored ->
messageService.send(
+ nodeId,
+ FACTORY.queryCloseMessage()
+
.queryId(ctx.queryId())
+ .build()
+ ))
);
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/MailboxRegistry.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/MailboxRegistry.java
index eed6a5d0ba..75676d435f 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/MailboxRegistry.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/MailboxRegistry.java
@@ -17,12 +17,10 @@
package org.apache.ignite.internal.sql.engine.exec;
-import java.util.Collection;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.apache.ignite.internal.sql.engine.exec.rel.Inbox;
import org.apache.ignite.internal.sql.engine.exec.rel.Outbox;
-import org.jetbrains.annotations.Nullable;
/**
* MailboxRegistry interface.
@@ -74,14 +72,4 @@ public interface MailboxRegistry extends LifecycleAware {
* @return Registered inbox. May be {@code null} if execution was
cancelled.
*/
Inbox<?> inbox(UUID qryId, long exchangeId);
-
- /**
- * Returns all registered inboxes for provided query ID.
- *
- * @param qryId Query ID. {@code null} means return inboxes with any
query id.
- * @param fragmentId Fragment Id. {@code -1} means return inboxes with any
fragment id.
- * @param exchangeId Exchange Id. {@code -1} means return inboxes with any
exchange id.
- * @return Registered inboxes.
- */
- Collection<Inbox<?>> inboxes(@Nullable UUID qryId, long fragmentId, long
exchangeId);
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/MailboxRegistryImpl.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/MailboxRegistryImpl.java
index aa939b9769..5124f72a2a 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/MailboxRegistryImpl.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/MailboxRegistryImpl.java
@@ -17,23 +17,17 @@
package org.apache.ignite.internal.sql.engine.exec;
-import java.util.Collection;
import java.util.Map;
-import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.sql.engine.exec.rel.Inbox;
-import org.apache.ignite.internal.sql.engine.exec.rel.Mailbox;
import org.apache.ignite.internal.sql.engine.exec.rel.Outbox;
import org.apache.ignite.internal.tostring.S;
import org.apache.ignite.network.ClusterNode;
import org.apache.ignite.network.TopologyEventHandler;
-import org.jetbrains.annotations.Nullable;
/**
* MailboxRegistryImpl.
@@ -42,8 +36,6 @@ import org.jetbrains.annotations.Nullable;
public class MailboxRegistryImpl implements MailboxRegistry,
TopologyEventHandler {
private static final IgniteLogger LOG =
Loggers.forClass(MailboxRegistryImpl.class);
- private static final Predicate<Mailbox<?>> ALWAYS_TRUE = o -> true;
-
private final Map<MailboxKey, CompletableFuture<Outbox<?>>> locals;
private final Map<MailboxKey, Inbox<?>> remotes;
@@ -124,29 +116,6 @@ public class MailboxRegistryImpl implements
MailboxRegistry, TopologyEventHandle
return remotes.get(new MailboxKey(qryId, exchangeId));
}
- /** {@inheritDoc} */
- @Override
- public Collection<Inbox<?>> inboxes(@Nullable UUID qryId, long fragmentId,
long exchangeId) {
- return remotes.values().stream()
- .filter(makeFilter(qryId, fragmentId, exchangeId))
- .collect(Collectors.toList());
- }
-
- private static Predicate<Mailbox<?>> makeFilter(@Nullable UUID qryId, long
fragmentId, long exchangeId) {
- Predicate<Mailbox<?>> filter = ALWAYS_TRUE;
- if (qryId != null) {
- filter = filter.and(mailbox -> Objects.equals(mailbox.queryId(),
qryId));
- }
- if (fragmentId != -1) {
- filter = filter.and(mailbox -> mailbox.fragmentId() == fragmentId);
- }
- if (exchangeId != -1) {
- filter = filter.and(mailbox -> mailbox.exchangeId() == exchangeId);
- }
-
- return filter;
- }
-
/** {@inheritDoc} */
@Override
public String toString() {
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Inbox.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Inbox.java
index 2c7f63a2b7..81aade9a57 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Inbox.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Inbox.java
@@ -35,7 +35,10 @@ import
org.apache.ignite.internal.sql.engine.exec.ExecutionContext;
import org.apache.ignite.internal.sql.engine.exec.MailboxRegistry;
import org.apache.ignite.internal.sql.engine.exec.SharedState;
import org.apache.ignite.internal.sql.engine.exec.rel.Inbox.RemoteSource.State;
+import org.apache.ignite.internal.util.ExceptionUtils;
+import org.apache.ignite.lang.ErrorGroups.Sql;
import org.apache.ignite.lang.IgniteInternalCheckedException;
+import org.apache.ignite.lang.IgniteInternalException;
import org.jetbrains.annotations.Nullable;
/**
@@ -174,10 +177,6 @@ public class Inbox<RowT> extends AbstractNode<RowT>
implements Mailbox<RowT>, Si
private void push() throws Exception {
if (remoteSources == null) {
- for (String node : srcNodeNames) {
- checkNode(node);
- }
-
remoteSources = new ArrayList<>(srcNodeNames.size());
for (String nodeName : srcNodeNames) {
@@ -334,8 +333,20 @@ public class Inbox<RowT> extends AbstractNode<RowT>
implements Mailbox<RowT>, Si
}
}
- private void requestBatches(String nodeName, int cnt, @Nullable
SharedState state) throws IgniteInternalCheckedException {
- exchange.request(nodeName, queryId(), srcFragmentId, exchangeId, cnt,
state);
+ private void requestBatches(String nodeName, int cnt, @Nullable
SharedState state) {
+ exchange.request(nodeName, queryId(), srcFragmentId, exchangeId, cnt,
state)
+ .whenComplete((ignored, ex) -> {
+ if (ex != null) {
+ IgniteInternalException wrapperEx =
ExceptionUtils.withCauseAndCode(
+ IgniteInternalException::new,
+ Sql.INTERNAL_ERR,
+ "Unable to request next batch: " +
ex.getMessage(),
+ ex
+ );
+
+ context().execute(() -> onError(wrapperEx),
this::onError);
+ }
+ });
}
/**
@@ -358,12 +369,6 @@ public class Inbox<RowT> extends AbstractNode<RowT>
implements Mailbox<RowT>, Si
}
}
- private void checkNode(String nodeName) throws
IgniteInternalCheckedException {
- if (!exchange.alive(nodeName)) {
- throw new IgniteInternalCheckedException(NODE_LEFT_ERR, "Failed to
execute query, node left [nodeName=" + nodeName + ']');
- }
- }
-
private static final class Batch<RowT> implements Comparable<Batch<RowT>> {
private final int batchId;
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Outbox.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Outbox.java
index dad5cbb4f9..0e30d48d4e 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Outbox.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Outbox.java
@@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
+import java.util.UUID;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.sql.engine.exec.ExchangeService;
@@ -34,7 +35,10 @@ import
org.apache.ignite.internal.sql.engine.exec.MailboxRegistry;
import org.apache.ignite.internal.sql.engine.exec.SharedState;
import org.apache.ignite.internal.sql.engine.trait.Destination;
import org.apache.ignite.internal.sql.engine.util.Commons;
+import org.apache.ignite.internal.util.ExceptionUtils;
+import org.apache.ignite.lang.ErrorGroups.Sql;
import org.apache.ignite.lang.IgniteInternalCheckedException;
+import org.apache.ignite.lang.IgniteInternalException;
import org.jetbrains.annotations.Nullable;
/**
@@ -172,13 +176,9 @@ public class Outbox<RowT> extends AbstractNode<RowT>
implements Mailbox<RowT>, S
/** {@inheritDoc} */
@Override
public void onError(Throwable e) {
- try {
- sendError(e);
- } catch (IgniteInternalCheckedException ex) {
- LOG.info("Unable to send error message", e);
- } finally {
- Commons.closeQuiet(this);
- }
+ sendError(e);
+
+ Commons.closeQuiet(this);
}
/** {@inheritDoc} */
@@ -231,20 +231,47 @@ public class Outbox<RowT> extends AbstractNode<RowT>
implements Mailbox<RowT>, S
return this;
}
- private void sendBatch(String nodeName, int batchId, boolean last,
List<RowT> rows) throws IgniteInternalCheckedException {
- exchange.sendBatch(nodeName, queryId(), targetFragmentId, exchangeId,
batchId, last, rows);
+ private void sendBatch(String nodeName, int batchId, boolean last,
List<RowT> rows) {
+ exchange.sendBatch(nodeName, queryId(), targetFragmentId, exchangeId,
batchId, last, rows)
+ .whenComplete((ignored, ex) -> {
+ if (ex == null) {
+ return;
+ }
+
+ IgniteInternalException wrapperEx =
ExceptionUtils.withCauseAndCode(
+ IgniteInternalException::new,
+ Sql.INTERNAL_ERR,
+ "Unable to send batch: " + ex.getMessage(),
+ ex
+ );
+
+ context().execute(() -> onError(wrapperEx), this::onError);
+ });
}
- private void sendError(Throwable err) throws
IgniteInternalCheckedException {
- exchange.sendError(context().originatingNodeName(), queryId(),
fragmentId(), err);
- }
-
- private void sendInboxClose(String nodeName) {
- try {
- exchange.closeInbox(nodeName, queryId(), targetFragmentId,
exchangeId);
- } catch (IgniteInternalCheckedException e) {
- LOG.info("Unable to send cancel message", e);
- }
+ private void sendError(Throwable original) {
+ String nodeName = context().originatingNodeName();
+ UUID queryId = queryId();
+ long fragmentId = fragmentId();
+
+ exchange.sendError(nodeName, queryId, fragmentId, original)
+ .whenComplete((ignored, ex) -> {
+ if (ex == null) {
+ return;
+ }
+
+ IgniteInternalException wrapperEx =
ExceptionUtils.withCauseAndCode(
+ IgniteInternalException::new,
+ Sql.INTERNAL_ERR,
+ "Unable to send error: " + ex.getMessage(),
+ ex
+ );
+
+ wrapperEx.addSuppressed(original);
+
+ LOG.warn("Unable to send error to a remote node
[queryId={}, fragmentId={}, targetNode={}]",
+ queryId, fragmentId, nodeName, wrapperEx);
+ });
}
private void flush() throws Exception {
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/InboxCloseMessage.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/InboxCloseMessage.java
deleted file mode 100644
index b8c7364c3a..0000000000
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/InboxCloseMessage.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.sql.engine.message;
-
-import java.io.Serializable;
-import java.util.UUID;
-import org.apache.ignite.network.NetworkMessage;
-import org.apache.ignite.network.annotations.Transferable;
-
-/**
- * InboxCloseMessage interface.
- * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
- */
-@Transferable(value = SqlQueryMessageGroup.INBOX_CLOSE_MESSAGE)
-public interface InboxCloseMessage extends NetworkMessage, Serializable {
- /**
- * Get query ID.
- */
- UUID queryId();
-
- /**
- * Get fragment ID.
- */
- long fragmentId();
-
- /**
- * Get exchange ID.
- */
- long exchangeId();
-}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/MessageService.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/MessageService.java
index 633ef7f86d..c7bad33de1 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/MessageService.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/MessageService.java
@@ -17,8 +17,8 @@
package org.apache.ignite.internal.sql.engine.message;
+import java.util.concurrent.CompletableFuture;
import org.apache.ignite.internal.sql.engine.exec.LifecycleAware;
-import org.apache.ignite.lang.IgniteInternalCheckedException;
import org.apache.ignite.network.NetworkMessage;
/**
@@ -32,15 +32,7 @@ public interface MessageService extends LifecycleAware {
* @param nodeName Node consistent ID.
* @param msg Message.
*/
- void send(String nodeName, NetworkMessage msg) throws
IgniteInternalCheckedException;
-
- /**
- * Checks whether a node with given ID is alive.
- *
- * @param nodeName Node consistent ID.
- * @return {@code True} if node is alive.
- */
- boolean alive(String nodeName);
+ CompletableFuture<Void> send(String nodeName, NetworkMessage msg);
/**
* Registers a listener for messages of a given type.
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/MessageServiceImpl.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/MessageServiceImpl.java
index a0010e81b9..b144fa69ef 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/MessageServiceImpl.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/MessageServiceImpl.java
@@ -18,15 +18,14 @@
package org.apache.ignite.internal.sql.engine.message;
import static
org.apache.ignite.internal.sql.engine.message.SqlQueryMessageGroup.GROUP_TYPE;
-import static org.apache.ignite.lang.ErrorGroups.Sql.MESSAGE_SEND_ERR;
import static org.apache.ignite.lang.ErrorGroups.Sql.NODE_LEFT_ERR;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
import org.apache.ignite.internal.sql.engine.exec.QueryTaskExecutor;
import org.apache.ignite.internal.util.IgniteSpinBusyLock;
-import org.apache.ignite.lang.IgniteInternalCheckedException;
import org.apache.ignite.lang.IgniteInternalException;
import org.apache.ignite.network.ClusterNode;
import org.apache.ignite.network.MessagingService;
@@ -77,33 +76,29 @@ public class MessageServiceImpl implements MessageService {
/** {@inheritDoc} */
@Override
- public void send(String nodeName, NetworkMessage msg) throws
IgniteInternalCheckedException {
+ public CompletableFuture<Void> send(String nodeName, NetworkMessage msg) {
if (!busyLock.enterBusy()) {
- return;
+ return CompletableFuture.completedFuture(null);
}
try {
if (locNodeName.equals(nodeName)) {
onMessage(nodeName, msg);
+
+ return CompletableFuture.completedFuture(null);
} else {
ClusterNode node = topSrvc.getByConsistentId(nodeName);
if (node == null) {
- throw new IgniteInternalException(
+ return CompletableFuture.failedFuture(new
IgniteInternalException(
NODE_LEFT_ERR, "Failed to send message to node
(has node left grid?): " + nodeName
- );
+ ));
}
- try {
- messagingSrvc.send(node, msg).join();
- } catch (Exception ex) {
- if (ex instanceof IgniteInternalCheckedException) {
- throw (IgniteInternalCheckedException) ex;
- }
-
- throw new IgniteInternalCheckedException(MESSAGE_SEND_ERR,
ex);
- }
+ return messagingSrvc.send(node, msg);
}
+ } catch (Exception ex) {
+ return CompletableFuture.failedFuture(ex);
} finally {
busyLock.leaveBusy();
}
@@ -121,12 +116,6 @@ public class MessageServiceImpl implements MessageService {
assert old == null : old;
}
- /** {@inheritDoc} */
- @Override
- public boolean alive(String nodeName) {
- return topSrvc.getByConsistentId(nodeName) != null;
- }
-
private void onMessage(String consistentId, NetworkMessage msg) {
if (msg instanceof ExecutionContextAwareMessage) {
ExecutionContextAwareMessage msg0 = (ExecutionContextAwareMessage)
msg;
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/SqlQueryMessageGroup.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/SqlQueryMessageGroup.java
index d4cc366191..e8d8355f71 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/SqlQueryMessageGroup.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/message/SqlQueryMessageGroup.java
@@ -39,7 +39,5 @@ public final class SqlQueryMessageGroup {
/** See {@link QueryBatchRequestMessage} for details. */
public static final short QUERY_BATCH_REQUEST = 4;
- public static final short INBOX_CLOSE_MESSAGE = 5;
-
- public static final short QUERY_CLOSE_MESSAGE = 6;
+ public static final short QUERY_CLOSE_MESSAGE = 5;
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/Cloner.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/Cloner.java
index e6adf7a2f5..8433032cbc 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/Cloner.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/Cloner.java
@@ -33,7 +33,7 @@ public class Cloner {
private List<IgniteReceiver> remotes;
- Cloner(RelOptCluster cluster) {
+ public Cloner(RelOptCluster cluster) {
this.cluster = cluster;
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/FragmentPlan.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/FragmentPlan.java
deleted file mode 100644
index 658b0874b8..0000000000
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/FragmentPlan.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.sql.engine.prepare;
-
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.ignite.internal.sql.engine.SqlQueryType;
-import org.apache.ignite.internal.sql.engine.rel.IgniteRel;
-import org.apache.ignite.internal.sql.engine.util.Commons;
-import org.apache.ignite.sql.ResultSetMetadata;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * FragmentPlan.
- * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
- */
-public class FragmentPlan implements QueryPlan {
- private final IgniteRel root;
-
- /**
- * Constructor.
- * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
- */
- public FragmentPlan(IgniteRel root) {
- RelOptCluster cluster = Commons.cluster();
-
- this.root = new Cloner(cluster).visit(root);
- }
-
- public IgniteRel root() {
- return root;
- }
-
- /** {@inheritDoc} */
- @Override
- public @Nullable SqlQueryType type() {
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- public ResultSetMetadata metadata() {
- throw new IllegalStateException("Metadata is not available for a
FragmentPlan.");
- }
-
- /** {@inheritDoc} */
- @Override
- public QueryPlan copy() {
- return this;
- }
-}
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java
index c78501322f..3c490600f7 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java
@@ -161,7 +161,6 @@ public class StopCalciteModuleTest {
when(clusterSrvc.topologyService()).thenReturn(topologySrvc);
when(topologySrvc.localMember()).thenReturn(localNode);
when(topologySrvc.allMembers()).thenReturn(List.of(localNode));
- when(topologySrvc.getByConsistentId(any())).thenReturn(localNode);
SchemaDescriptor schemaDesc = new SchemaDescriptor(
1,
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImplTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImplTest.java
index c2ab89e1d6..d9ee94036c 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImplTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImplTest.java
@@ -96,7 +96,6 @@ import
org.apache.ignite.internal.testframework.IgniteTestUtils.RunnableX;
import org.apache.ignite.internal.tx.InternalTransaction;
import org.apache.ignite.internal.util.ArrayUtils;
import org.apache.ignite.lang.ErrorGroups.Sql;
-import org.apache.ignite.lang.IgniteInternalCheckedException;
import org.apache.ignite.lang.IgniteInternalException;
import org.apache.ignite.network.ClusterNode;
import org.apache.ignite.network.NetworkAddress;
@@ -233,19 +232,17 @@ public class ExecutionServiceImplTest {
testCluster.node(nodeNames.get(2)).interceptor((nodeName, msg,
original) -> {
if (msg instanceof QueryStartRequest) {
- try {
-
testCluster.node(nodeNames.get(2)).messageService().send(nodeName, new
SqlQueryMessagesFactory().queryStartResponse()
- .queryId(((QueryStartRequest) msg).queryId())
- .fragmentId(((QueryStartRequest) msg).fragmentId())
- .error(expectedEx)
- .build()
- );
- } catch (IgniteInternalCheckedException e) {
- throw new
IgniteInternalException(OPERATION_INTERRUPTED_ERR, e);
- }
+
testCluster.node(nodeNames.get(2)).messageService().send(nodeName, new
SqlQueryMessagesFactory().queryStartResponse()
+ .queryId(((QueryStartRequest) msg).queryId())
+ .fragmentId(((QueryStartRequest) msg).fragmentId())
+ .error(expectedEx)
+ .build()
+ );
} else {
original.onMessage(nodeName, msg);
}
+
+ return CompletableFuture.completedFuture(null);
});
InternalTransaction tx = new NoOpTransaction(nodeNames.get(0));
@@ -416,10 +413,12 @@ public class ExecutionServiceImplTest {
original.onMessage(senderNodeName, msg);
});
+
+ return CompletableFuture.completedFuture(null);
} else {
// On other nodes, simulate that the node has already gone.
- throw new IgniteInternalException(Sql.MESSAGE_SEND_ERR,
- "Connection refused to " + node.nodeName + ", message
" + msg);
+ return CompletableFuture.failedFuture(new
IgniteInternalException(Sql.INTERNAL_ERR,
+ "Connection refused to " + node.nodeName + ", message
" + msg));
}
}));
@@ -485,7 +484,6 @@ public class ExecutionServiceImplTest {
mock(DdlCommandHandler.class),
taskExecutor,
ArrayRowHandler.INSTANCE,
- exchangeService,
ctx -> node.implementor(ctx, mailboxRegistry, exchangeService)
);
@@ -538,7 +536,6 @@ public class ExecutionServiceImplTest {
class TestNode {
private final Map<Short, MessageListener> msgListeners = new
ConcurrentHashMap<>();
private final Queue<RunnableX> pending = new
LinkedBlockingQueue<>();
- private volatile boolean dead = false;
private volatile List<Object[]> dataset = List.of();
private volatile MessageInterceptor interceptor = null;
@@ -552,14 +549,6 @@ public class ExecutionServiceImplTest {
this.taskExecutor = taskExecutor;
}
- public void dead(boolean dead) {
- this.dead = dead;
- }
-
- public boolean dead() {
- return dead;
- }
-
public void dataset(List<Object[]> dataset) {
this.dataset = dataset;
}
@@ -597,16 +586,10 @@ public class ExecutionServiceImplTest {
return new MessageService() {
/** {@inheritDoc} */
@Override
- public void send(String nodeName, NetworkMessage msg) {
+ public CompletableFuture<Void> send(String nodeName,
NetworkMessage msg) {
TestNode node = nodes.get(nodeName);
- node.onReceive(TestNode.this.nodeName, msg);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean alive(String nodeName) {
- return !nodes.get(nodeName).dead();
+ return node.onReceive(TestNode.this.nodeName, msg);
}
/** {@inheritDoc} */
@@ -665,7 +648,7 @@ public class ExecutionServiceImplTest {
};
}
- private void onReceive(String senderNodeName, NetworkMessage
message) {
+ private CompletableFuture<Void> onReceive(String senderNodeName,
NetworkMessage message) {
MessageListener original = (nodeName, msg) -> {
MessageListener listener =
msgListeners.get(msg.messageType());
@@ -685,15 +668,18 @@ public class ExecutionServiceImplTest {
MessageInterceptor interceptor = this.interceptor;
if (interceptor != null) {
- interceptor.intercept(senderNodeName, message, original);
- } else {
- original.onMessage(senderNodeName, message);
+ return interceptor.intercept(senderNodeName, message,
original);
}
+
+ original.onMessage(senderNodeName, message);
+
+ return CompletableFuture.completedFuture(null);
}
}
+ @FunctionalInterface
interface MessageInterceptor {
- void intercept(String senderNodeName, NetworkMessage msg,
MessageListener original);
+ CompletableFuture<Void> intercept(String senderNodeName,
NetworkMessage msg, MessageListener original);
}
}
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestNode.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestNode.java
index 9678100c33..038cf54743 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestNode.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/TestNode.java
@@ -120,7 +120,6 @@ public class TestNode implements LifecycleAware {
mock(DdlCommandHandler.class),
taskExecutor,
rowHandler,
- exchangeService,
ctx -> new LogicalRelImplementor<Object[]>(
ctx,
new HashFunctionFactoryImpl<>(schemaManager,
rowHandler),