You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ap...@apache.org on 2024/06/28 19:38:10 UTC
(ignite-3) branch main updated: IGNITE-22478 Use single argument in Compute API (#3926)
This is an automated email from the ASF dual-hosted git repository.
apkhmv 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 692ecdedc2 IGNITE-22478 Use single argument in Compute API (#3926)
692ecdedc2 is described below
commit 692ecdedc2d8cfea713c3dbea17f16579e4aa551
Author: Aleksandr Pakhomov <ap...@gmail.com>
AuthorDate: Fri Jun 28 22:38:05 2024 +0300
IGNITE-22478 Use single argument in Compute API (#3926)
The Compute API is changed:
- Only single argument can be accepted or null by any compute job.
- Marshaler API is introduced as a part of public API and can be used in Compute API.
- Default marshaller is implemented but not used explicitly. By default we support only
primitives. If the one want to use custom marshaler they should declare it explicitly.
Marshalers allow us to define the default way to serialize objects: java serialization.
At the same time client can implement theirs own marshalers and use them in any
public API that supports it. This is the first implementation and it is supposed to be
improved in the future. The only thing that will not be changed -- Marshaler and
Compute interfaces (their public parts).
---
.../java/org/apache/ignite/compute/ComputeJob.java | 35 +++-
.../org/apache/ignite/compute/IgniteCompute.java | 98 +++++----
.../org/apache/ignite/compute/JobDescriptor.java | 77 +++++--
.../apache/ignite/compute/task/MapReduceJob.java | 43 ++--
.../apache/ignite/compute/task/MapReduceTask.java | 18 +-
.../java/org/apache/ignite/lang/ErrorGroups.java | 25 ++-
.../ignite/marshaling/ByteArrayMarshaler.java | 56 ++++++
.../JavaSerializationByteArrayMarshallilng.java | 70 +++++++
.../org/apache/ignite/marshaling/Marshaler.java | 57 ++++++
.../ignite/marshaling/MarshallingException.java | 50 +++++
.../apache/ignite/marshaling/TupleMarshaller.java} | 21 +-
.../UnsupportedObjectTypeMarshalingException.java | 53 +++++
.../apache/ignite/table/DataStreamerReceiver.java | 11 +-
.../apache/ignite/table/DataStreamerTarget.java | 9 +-
.../apache/ignite/table/ReceiverDescriptor.java | 46 +++--
.../ignite/marshaling/ByteArrayMarshalerTest.java | 167 +++++++++++++++
.../client/proto/ClientBinaryTupleUtils.java | 8 +-
.../internal/client/proto/ClientMessagePacker.java | 13 +-
.../client/proto/ClientMessageUnpacker.java | 11 +
.../client/proto/StreamerReceiverSerializer.java | 30 ++-
.../proto/event/JdbcBatchPreparedStmntRequest.java | 2 +-
.../jdbc/proto/event/JdbcQueryExecuteRequest.java | 10 +-
.../proto/ClientMessagePackerUnpackerTest.java | 8 +-
.../ClientComputeExecuteColocatedRequest.java | 6 +-
.../ClientComputeExecuteMapReduceRequest.java | 6 +-
.../compute/ClientComputeExecuteRequest.java | 19 +-
...ClientStreamerWithReceiverBatchSendRequest.java | 35 ++--
.../apache/ignite/client/ClientOperationType.java | 4 +-
.../internal/client/compute/ClientCompute.java | 124 +++++++-----
.../client/compute/ClientJobExecution.java | 7 +-
.../ignite/internal/client/sql/ClientSql.java | 6 +-
.../internal/client/table/ClientDataStreamer.java | 11 +-
.../client/table/ClientKeyValueBinaryView.java | 10 +-
.../internal/client/table/ClientKeyValueView.java | 10 +-
.../client/table/ClientRecordBinaryView.java | 10 +-
.../internal/client/table/ClientRecordView.java | 10 +-
.../apache/ignite/client/ClientComputeTest.java | 61 ++++--
.../org/apache/ignite/client/DataStreamerTest.java | 83 +++++---
.../ignite/client/PartitionAwarenessTest.java | 30 +--
.../apache/ignite/client/RequestBalancingTest.java | 2 +-
.../apache/ignite/client/ServerMetricsTest.java | 8 +-
.../apache/ignite/client/fakes/FakeCompute.java | 25 +--
.../ignite/internal/compute/ItComputeBaseTest.java | 105 +++++++---
.../internal/compute/ItComputeErrorsBaseTest.java | 12 +-
.../internal/compute/ItComputeTestEmbedded.java | 45 +++--
.../internal/compute/ItComputeTestStandalone.java | 8 +-
.../internal/compute/ItExecutionsCleanerTest.java | 5 +-
.../compute/ItFailoverCandidateNotFoundTest.java | 2 +-
.../ignite/internal/compute/ItMapReduceTest.java | 22 +-
.../internal/compute/ItWorkerShutdownTest.java | 7 +-
.../threading/ItComputeApiThreadingTest.java | 29 +--
.../internal/compute/utils/InteractiveJobs.java | 30 +--
.../internal/compute/utils/InteractiveTasks.java | 31 ++-
.../apache/ignite/internal/compute/ConcatJob.java | 7 +-
.../apache/ignite/internal/compute/FailingJob.java | 4 +-
.../ignite/internal/compute/GetNodeNameJob.java | 4 +-
.../apache/ignite/internal/compute/MapReduce.java | 14 +-
.../internal/compute/NonEmptyConstructorJob.java | 4 +-
.../internal/compute/{SleepJob.java => Pojo.java} | 50 +++--
.../{NonEmptyConstructorJob.java => PojoJob.java} | 26 ++-
.../apache/ignite/internal/compute/SleepJob.java | 6 +-
.../internal/compute/AntiHijackIgniteCompute.java | 16 +-
.../ignite/internal/compute/ComputeComponent.java | 43 ++--
.../internal/compute/ComputeComponentImpl.java | 41 ++--
.../internal/compute/ComputeJobFailover.java | 23 ++-
.../ignite/internal/compute/ComputeUtils.java | 24 +--
.../ignite/internal/compute/IgniteComputeImpl.java | 57 ++++--
.../internal/compute/IgniteComputeInternal.java | 8 +-
.../apache/ignite/internal/compute/JobStarter.java | 2 +-
.../internal/compute/RemoteExecutionContext.java | 26 +--
.../internal/compute/executor/ComputeExecutor.java | 12 +-
.../compute/executor/ComputeExecutorImpl.java | 34 +++-
.../internal/compute/message/ExecuteRequest.java | 3 +-
.../compute/messaging/ComputeMessaging.java | 12 +-
.../compute/task/DelegatingTaskExecution.java | 6 +-
.../ignite/internal/compute/task/JobSubmitter.java | 4 +-
.../compute/task/TaskExecutionInternal.java | 45 +++--
.../internal/compute/ComputeComponentImplTest.java | 70 ++++---
.../internal/compute/IgniteComputeImplTest.java | 26 +--
.../compute/executor/ComputeExecutorTest.java | 37 ++--
.../compute/loader/JobClassLoaderFactoryTest.java | 12 +-
.../apache/ignite/internal/compute/UnitJob.java | 4 +-
.../apache/ignite/internal/compute/UnitJob.java | 4 +-
.../cpp/ignite/client/compute/compute.cpp | 13 +-
.../platforms/cpp/ignite/client/compute/compute.h | 31 +--
.../cpp/ignite/client/compute/job_descriptor.h | 20 +-
.../cpp/ignite/client/compute/job_execution.cpp | 2 +-
.../cpp/ignite/client/compute/job_execution.h | 9 +-
.../ignite/client/detail/compute/compute_impl.cpp | 35 ++--
.../ignite/client/detail/compute/compute_impl.h | 9 +-
.../client/detail/compute/job_execution_impl.cpp | 13 +-
.../client/detail/compute/job_execution_impl.h | 6 +-
.../cpp/ignite/common/binary_object.h} | 39 +++-
modules/platforms/cpp/ignite/common/error_codes.h | 9 +-
modules/platforms/cpp/ignite/odbc/common_types.cpp | 5 +
.../cpp/tests/client-test/compute_test.cpp | 145 +++++++-------
.../cpp/tests/client-test/ignite_runner_suite.h | 1 +
.../client-test/schema_synchronization_test.cpp | 2 +-
.../cpp/tests/test-common/basic_auth_test_suite.h | 2 +-
.../Apache.Ignite.Tests/BasicAuthenticatorTests.cs | 2 +-
.../Compute/ComputeClusterAwarenessTests.cs | 16 +-
.../Apache.Ignite.Tests/Compute/ComputeTests.cs | 113 +++++------
.../dotnet/Apache.Ignite.Tests/FakeServer.cs | 2 +-
.../PartitionAwarenessRealClusterTests.cs | 3 +-
.../Apache.Ignite.Tests/PartitionAwarenessTests.cs | 19 +-
.../Proto/ColocationHashTests.cs | 31 ++-
.../Apache.Ignite.Tests/Table/DataStreamerTests.cs | 76 +++----
.../Table/SchemaSynchronizationTest.cs | 9 +-
.../dotnet/Apache.Ignite/ClientOperationType.cs | 2 +-
.../dotnet/Apache.Ignite/Compute/ICompute.cs | 18 +-
.../dotnet/Apache.Ignite/Compute/JobDescriptor.cs | 12 +-
.../platforms/dotnet/Apache.Ignite/ErrorCodes.g.cs | 17 ++
.../Apache.Ignite/Internal/Compute/Compute.cs | 65 +++---
.../Internal/Proto/MsgPack/MsgPackWriter.cs | 18 ++
.../Internal/Table/DataStreamerWithReceiver.cs | 22 +-
.../Apache.Ignite/Internal/Table/KeyValueView.cs | 16 +-
.../Apache.Ignite/Internal/Table/RecordView.cs | 18 +-
.../Apache.Ignite/Table/IDataStreamerTarget.cs | 18 +-
.../Apache.Ignite/Table/ReceiverDescriptor.cs | 15 +-
.../rest/compute/ItComputeControllerTest.java | 6 +-
.../runner/app/PlatformTestNodeRunner.java | 86 ++++----
.../client/ItThinClientComputeMarshallingTest.java | 140 +++++++++++++
.../runner/app/client/ItThinClientComputeTest.java | 223 ++++++++++++---------
.../client/ItThinClientPartitionAwarenessTest.java | 9 +-
.../streamer/ItAbstractDataStreamerTest.java | 28 ++-
.../internal/table/KeyValueBinaryViewImpl.java | 6 +-
.../ignite/internal/table/KeyValueViewImpl.java | 6 +-
.../internal/table/PublicApiThreadingViewBase.java | 8 +-
.../internal/table/RecordBinaryViewImpl.java | 6 +-
.../ignite/internal/table/RecordViewImpl.java | 6 +-
130 files changed, 2386 insertions(+), 1276 deletions(-)
diff --git a/modules/api/src/main/java/org/apache/ignite/compute/ComputeJob.java b/modules/api/src/main/java/org/apache/ignite/compute/ComputeJob.java
index 97db8b05ea..1d07567561 100644
--- a/modules/api/src/main/java/org/apache/ignite/compute/ComputeJob.java
+++ b/modules/api/src/main/java/org/apache/ignite/compute/ComputeJob.java
@@ -18,21 +18,46 @@
package org.apache.ignite.compute;
import java.util.concurrent.CompletableFuture;
+import org.apache.ignite.marshaling.Marshaler;
import org.jetbrains.annotations.Nullable;
/**
- * A Compute job that may be executed on a single Ignite node, on several nodes, or on the entire cluster.
+ * Core Ignite Compute Job interface. If you want to define your own job, you should implement this interface and
+ * deploy the job to the cluster with Deployment API. Then, you can execute this job on the cluster by calling
+ * {@link IgniteCompute} APIs.
*
- * @param <R> Job result type.
+ * <p>If you want to pass/return custom data structures to/from the job, you should also implement {@link Marshaler}
+ * and return it from {@link #inputMarshaler()} and {@link #resultMarshaler()} methods.
+ *
+ * @param <T> Type of the job argument.
+ * @param <R> Type of the job result.
*/
@SuppressWarnings("InterfaceMayBeAnnotatedFunctional")
-public interface ComputeJob<R> {
+public interface ComputeJob<T, R> {
/**
* Executes the job on an Ignite node.
*
* @param context The execution context.
- * @param args Job arguments.
+ * @param arg Job arguments.
* @return Job future. Can be null if the job is synchronous and does not return any result.
*/
- @Nullable CompletableFuture<R> executeAsync(JobExecutionContext context, Object... args);
+ @Nullable CompletableFuture<R> executeAsync(JobExecutionContext context, @Nullable T arg);
+
+ /**
+ * Marshaler for the input argument. Default is {@code null} meaning that only primitive types are supported.
+ *
+ * @return Input marshaler.
+ */
+ default @Nullable Marshaler<T, byte[]> inputMarshaler() {
+ return null;
+ }
+
+ /**
+ * Marshaler for the job result. Default is {@code null} meaning that only primitive types are supported.
+ *
+ * @return Result marshaler.
+ */
+ default @Nullable Marshaler<R, byte[]> resultMarshaler() {
+ return null;
+ }
}
diff --git a/modules/api/src/main/java/org/apache/ignite/compute/IgniteCompute.java b/modules/api/src/main/java/org/apache/ignite/compute/IgniteCompute.java
index fe7048dc05..f5569d4056 100644
--- a/modules/api/src/main/java/org/apache/ignite/compute/IgniteCompute.java
+++ b/modules/api/src/main/java/org/apache/ignite/compute/IgniteCompute.java
@@ -31,94 +31,100 @@ import org.apache.ignite.compute.task.MapReduceTask;
import org.apache.ignite.compute.task.TaskExecution;
import org.apache.ignite.deployment.DeploymentUnit;
import org.apache.ignite.network.ClusterNode;
+import org.jetbrains.annotations.Nullable;
/**
* Provides the ability to execute Compute jobs.
*
* @see ComputeJob
- * @see ComputeJob#executeAsync(JobExecutionContext, Object...)
+ * @see ComputeJob#executeAsync(JobExecutionContext, Object)
*/
public interface IgniteCompute {
/**
* Submits a {@link ComputeJob} of the given class for an execution on a single node from a set of candidate nodes.
*
- * @param <R> Job result type.
+ * @param <T> Job argument (T)ype.
+ * @param <R> Job (R)esult type.
* @param target Execution target.
* @param descriptor Job descriptor.
- * @param args Arguments of the job.
+ * @param arg Argument of the job.
* @return Job execution object.
*/
- <R> JobExecution<R> submit(
+ <T, R> JobExecution<R> submit(
JobTarget target,
- JobDescriptor descriptor,
- Object... args
+ JobDescriptor<T, R> descriptor,
+ @Nullable T arg
);
/**
* Submits a {@link ComputeJob} of the given class for an execution on a single node from a set of candidate nodes. A shortcut for
* {@code submit(...).resultAsync()}.
*
- * @param <R> Job result type.
+ * @param <T> Job argument (T)ype.
+ * @param <R> Job (R)esult type.
* @param target Execution target.
* @param descriptor Job descriptor.
- * @param args Arguments of the job.
+ * @param arg Argument of the job.
* @return Job result future.
*/
- default <R> CompletableFuture<R> executeAsync(
+ default <T, R> CompletableFuture<R> executeAsync(
JobTarget target,
- JobDescriptor descriptor,
- Object... args
+ JobDescriptor<T, R> descriptor,
+ @Nullable T arg
) {
- return this.<R>submit(target, descriptor, args).resultAsync();
+ return submit(target, descriptor, arg).resultAsync();
}
/**
* Executes a {@link ComputeJob} of the given class on a single node from a set of candidate nodes.
*
- * @param <R> Job result type
+ * @param <T> Job argument (T)ype.
+ * @param <R> Job (R)esult type.
* @param target Execution target.
* @param descriptor Job descriptor.
- * @param args Arguments of the job.
+ * @param arg Argument of the job.
* @return Job result.
* @throws ComputeException If there is any problem executing the job.
*/
- <R> R execute(
+ <T, R> R execute(
JobTarget target,
- JobDescriptor descriptor,
- Object... args
+ JobDescriptor<T, R> descriptor,
+ @Nullable T arg
);
/**
* Submits a {@link ComputeJob} of the given class for an execution on all nodes in the given node set.
*
- * @param <R> Job result type.
+ * @param <T> Job argument (T)ype.
+ * @param <R> Job (R)esult type.
* @param nodes Nodes to execute the job on.
* @param descriptor Job descriptor.
- * @param args Arguments of the job.
+ * @param arg Argument of the job.
* @return Map from node to job execution object.
*/
- <R> Map<ClusterNode, JobExecution<R>> submitBroadcast(
+ <T, R> Map<ClusterNode, JobExecution<R>> submitBroadcast(
Set<ClusterNode> nodes,
- JobDescriptor descriptor,
- Object... args
+ JobDescriptor<T, R> descriptor,
+ @Nullable T arg
);
/**
* Executes a {@link ComputeJob} of the given class on all nodes in the given node set.
*
- * @param <R> Job result type.
+ * @param <T> Job argument (T)ype.
+ * @param <R> Job (R)esult type.
* @param nodes Nodes to execute the job on.
* @param descriptor Job descriptor.
- * @param args Arguments of the job.
+ * @param arg Argument of the job.
* @return Map from node to job result.
*/
- default <R> CompletableFuture<Map<ClusterNode, R>> executeBroadcastAsync(
+ default <T, R> CompletableFuture<Map<ClusterNode, R>> executeBroadcastAsync(
Set<ClusterNode> nodes,
- JobDescriptor descriptor,
- Object... args
+ JobDescriptor<T, R> descriptor,
+ @Nullable T arg
) {
Map<ClusterNode, CompletableFuture<R>> futures = nodes.stream()
- .collect(toMap(identity(), node -> this.executeAsync(JobTarget.node(node), descriptor, args)));
+ .collect(toMap(identity(), node -> executeAsync(JobTarget.node(node), descriptor, arg)));
return allOf(futures.values().toArray(CompletableFuture[]::new))
.thenApply(ignored -> {
@@ -136,22 +142,23 @@ public interface IgniteCompute {
/**
* Executes a {@link ComputeJob} of the given class on all nodes in the given node set.
*
- * @param <R> Job result type.
+ * @param <T> Job argument (T)ype.
+ * @param <R> Job (R)esult type.
* @param nodes Nodes to execute the job on.
* @param descriptor Job descriptor.
- * @param args Arguments of the job.
+ * @param arg Argument of the job.
* @return Map from node to job result.
* @throws ComputeException If there is any problem executing the job.
*/
- default <R> Map<ClusterNode, R> executeBroadcast(
+ default <T, R> Map<ClusterNode, R> executeBroadcast(
Set<ClusterNode> nodes,
- JobDescriptor descriptor,
- Object... args
+ JobDescriptor<T, R> descriptor,
+ @Nullable T arg
) {
Map<ClusterNode, R> map = new HashMap<>();
for (ClusterNode node : nodes) {
- map.put(node, execute(JobTarget.node(node), descriptor, args));
+ map.put(node, execute(JobTarget.node(node), descriptor, arg));
}
return map;
@@ -160,36 +167,39 @@ public interface IgniteCompute {
/**
* Submits a {@link MapReduceTask} of the given class for an execution.
*
+ * @param <T> Job argument (T)ype.
+ * @param <R> Job (R)esult type.
* @param units Deployment units.
* @param taskClassName Map reduce task class name.
- * @param args Task arguments.
- * @param <R> Task result type.
+ * @param arg Task argument.
* @return Task execution interface.
*/
- <R> TaskExecution<R> submitMapReduce(List<DeploymentUnit> units, String taskClassName, Object... args);
+ <T, R> TaskExecution<R> submitMapReduce(List<DeploymentUnit> units, String taskClassName, @Nullable T arg);
/**
* Submits a {@link MapReduceTask} of the given class for an execution. A shortcut for {@code submitMapReduce(...).resultAsync()}.
*
+ * @param <T> Job argument (T)ype.
+ * @param <R> Job (R)esult type.
* @param units Deployment units.
* @param taskClassName Map reduce task class name.
- * @param args Task arguments.
- * @param <R> Task result type.
+ * @param arg Task argument.
* @return Task result future.
*/
- default <R> CompletableFuture<R> executeMapReduceAsync(List<DeploymentUnit> units, String taskClassName, Object... args) {
- return this.<R>submitMapReduce(units, taskClassName, args).resultAsync();
+ default <T, R> CompletableFuture<R> executeMapReduceAsync(List<DeploymentUnit> units, String taskClassName, @Nullable T arg) {
+ return this.<T, R>submitMapReduce(units, taskClassName, arg).resultAsync();
}
/**
* Executes a {@link MapReduceTask} of the given class.
*
+ * @param <T> Job argument (T)ype.
+ * @param <R> Job (R)esult type.
* @param units Deployment units.
* @param taskClassName Map reduce task class name.
- * @param args Task arguments.
- * @param <R> Task result type.
+ * @param arg Task argument.
* @return Task result.
* @throws ComputeException If there is any problem executing the task.
*/
- <R> R executeMapReduce(List<DeploymentUnit> units, String taskClassName, Object... args);
+ <T, R> R executeMapReduce(List<DeploymentUnit> units, String taskClassName, @Nullable T arg);
}
diff --git a/modules/api/src/main/java/org/apache/ignite/compute/JobDescriptor.java b/modules/api/src/main/java/org/apache/ignite/compute/JobDescriptor.java
index 341c7f5b5b..02024bf86e 100644
--- a/modules/api/src/main/java/org/apache/ignite/compute/JobDescriptor.java
+++ b/modules/api/src/main/java/org/apache/ignite/compute/JobDescriptor.java
@@ -20,21 +20,35 @@ package org.apache.ignite.compute;
import java.util.List;
import java.util.Objects;
import org.apache.ignite.deployment.DeploymentUnit;
+import org.apache.ignite.marshaling.Marshaler;
+import org.jetbrains.annotations.Nullable;
/**
* Compute job descriptor.
*/
-public class JobDescriptor {
+public class JobDescriptor<T, R> {
private final String jobClassName;
private final List<DeploymentUnit> units;
private final JobExecutionOptions options;
- private JobDescriptor(String jobClassName, List<DeploymentUnit> units, JobExecutionOptions options) {
+ private final @Nullable Marshaler<R, byte[]> resultMarshaller;
+
+ private final @Nullable Marshaler<T, byte[]> argumentMarshaler;
+
+ private JobDescriptor(
+ String jobClassName,
+ List<DeploymentUnit> units,
+ JobExecutionOptions options,
+ @Nullable Marshaler<T, byte[]> argumentMarshaller,
+ @Nullable Marshaler<R, byte[]> resultMarshaller
+ ) {
this.jobClassName = jobClassName;
this.units = units;
this.options = options;
+ this.argumentMarshaler = argumentMarshaller;
+ this.resultMarshaller = resultMarshaller;
}
/**
@@ -69,10 +83,10 @@ public class JobDescriptor {
*
* @return Job descriptor builder.
*/
- public static Builder builder(String jobClassName) {
+ public static <T, R> Builder<T, R> builder(String jobClassName) {
Objects.requireNonNull(jobClassName);
- return new Builder(jobClassName);
+ return new Builder<>(jobClassName);
}
/**
@@ -80,19 +94,29 @@ public class JobDescriptor {
*
* @return Job descriptor builder.
*/
- public static Builder builder(Class<? extends ComputeJob<?>> jobClass) {
+ public static <T, R> Builder<T, R> builder(Class<? extends ComputeJob<T, R>> jobClass) {
Objects.requireNonNull(jobClass);
- return new Builder(jobClass.getName());
+ return new Builder<>(jobClass.getName());
+ }
+
+ public @Nullable Marshaler<R, byte[]> resultMarshaller() {
+ return resultMarshaller;
+ }
+
+ public @Nullable Marshaler<T, byte[]> argumentMarshaler() {
+ return argumentMarshaler;
}
/**
* Builder.
*/
- public static class Builder {
+ public static class Builder<T, R> {
private final String jobClassName;
private List<DeploymentUnit> units;
private JobExecutionOptions options;
+ private Marshaler<T, byte[]> argumentMarshaller;
+ private Marshaler<R, byte[]> resultMarshaller;
private Builder(String jobClassName) {
Objects.requireNonNull(jobClassName);
@@ -106,7 +130,7 @@ public class JobDescriptor {
* @param units Deployment units.
* @return This builder.
*/
- public Builder units(List<DeploymentUnit> units) {
+ public Builder<T, R> units(List<DeploymentUnit> units) {
this.units = units;
return this;
}
@@ -117,7 +141,7 @@ public class JobDescriptor {
* @param units Deployment units.
* @return This builder.
*/
- public Builder units(DeploymentUnit... units) {
+ public Builder<T, R> units(DeploymentUnit... units) {
this.units = List.of(units);
return this;
}
@@ -128,21 +152,48 @@ public class JobDescriptor {
* @param options Job execution options.
* @return This builder.
*/
- public Builder options(JobExecutionOptions options) {
+ public Builder<T, R> options(JobExecutionOptions options) {
this.options = options;
return this;
}
+ /**
+ * Sets the result marshaller.
+ *
+ * @param marshaller Result marshaller.
+ *
+ * @return This builder.
+ */
+ public Builder<T, R> resultMarshaller(Marshaler<R, byte[]> marshaller) {
+ this.resultMarshaller = marshaller;
+ return this;
+ }
+
+ /**
+ * Sets the argument marshaller.
+ *
+ * @param marshaller Argument marshaller.
+ *
+ * @return This builder.
+ */
+ public Builder<T, R> argumentMarshaller(Marshaler<T, byte[]> marshaller) {
+ this.argumentMarshaller = marshaller;
+ return this;
+ }
+
/**
* Builds the job descriptor.
*
* @return Job descriptor.
*/
- public JobDescriptor build() {
- return new JobDescriptor(
+ public JobDescriptor<T, R> build() {
+ return new JobDescriptor<>(
jobClassName,
units == null ? List.of() : units,
- options == null ? JobExecutionOptions.DEFAULT : options);
+ options == null ? JobExecutionOptions.DEFAULT : options,
+ argumentMarshaller,
+ resultMarshaller
+ );
}
}
}
diff --git a/modules/api/src/main/java/org/apache/ignite/compute/task/MapReduceJob.java b/modules/api/src/main/java/org/apache/ignite/compute/task/MapReduceJob.java
index 8b9e7a90b5..3819bc2458 100644
--- a/modules/api/src/main/java/org/apache/ignite/compute/task/MapReduceJob.java
+++ b/modules/api/src/main/java/org/apache/ignite/compute/task/MapReduceJob.java
@@ -27,20 +27,19 @@ import org.apache.ignite.network.ClusterNode;
/**
* A description of the job to be submitted as a result of the split step of the {@link MapReduceTask}. Reflects the parameters of the
- * {@link org.apache.ignite.compute.IgniteCompute#submit(JobTarget, JobDescriptor, Object...)} method.
+ * {@link org.apache.ignite.compute.IgniteCompute#submit(JobTarget, JobDescriptor, Object)} method.
*/
-public class MapReduceJob {
+public class MapReduceJob<T, R> {
private final Set<ClusterNode> nodes;
- private final JobDescriptor jobDescriptor;
+ private final JobDescriptor<T, R> jobDescriptor;
-
- private final Object[] args;
+ private final T args;
private MapReduceJob(
Set<ClusterNode> nodes,
- JobDescriptor jobDescriptor,
- Object[] args
+ JobDescriptor<T, R> jobDescriptor,
+ T args
) {
this.nodes = Collections.unmodifiableSet(nodes);
this.jobDescriptor = jobDescriptor;
@@ -61,7 +60,7 @@ public class MapReduceJob {
*
* @return Job descriptor.
*/
- public JobDescriptor jobDescriptor() {
+ public JobDescriptor<T, R> jobDescriptor() {
return jobDescriptor;
}
@@ -70,7 +69,7 @@ public class MapReduceJob {
*
* @return Arguments of the job.
*/
- public Object[] args() {
+ public T arg() {
return args;
}
@@ -79,8 +78,8 @@ public class MapReduceJob {
*
* @return New builder.
*/
- public ComputeJobRunnerBuilder toBuilder() {
- return builder().nodes(nodes).jobDescriptor(jobDescriptor).args(args);
+ public ComputeJobRunnerBuilder<T, R> toBuilder() {
+ return MapReduceJob.<T, R>builder().jobDescriptor(jobDescriptor).nodes(nodes).args(args);
}
/**
@@ -88,19 +87,19 @@ public class MapReduceJob {
*
* @return New builder.
*/
- public static ComputeJobRunnerBuilder builder() {
- return new ComputeJobRunnerBuilder();
+ public static <T, R> ComputeJobRunnerBuilder<T, R> builder() {
+ return new ComputeJobRunnerBuilder<>();
}
/**
* Job submit parameters builder.
*/
- public static class ComputeJobRunnerBuilder {
+ public static class ComputeJobRunnerBuilder<T, R> {
private final Set<ClusterNode> nodes = new HashSet<>();
- private JobDescriptor jobDescriptor;
+ private JobDescriptor<T, R> jobDescriptor;
- private Object[] args;
+ private T args;
/**
* Adds nodes to the set of candidate nodes.
@@ -108,7 +107,7 @@ public class MapReduceJob {
* @param nodes A collection of candidate nodes.
* @return Builder instance.
*/
- public ComputeJobRunnerBuilder nodes(Collection<ClusterNode> nodes) {
+ public ComputeJobRunnerBuilder<T, R> nodes(Collection<ClusterNode> nodes) {
this.nodes.addAll(nodes);
return this;
}
@@ -119,7 +118,7 @@ public class MapReduceJob {
* @param node Candidate node.
* @return Builder instance.
*/
- public ComputeJobRunnerBuilder node(ClusterNode node) {
+ public ComputeJobRunnerBuilder<T, R> node(ClusterNode node) {
nodes.add(node);
return this;
}
@@ -130,7 +129,7 @@ public class MapReduceJob {
* @param jobDescriptor A job descriptor.
* @return Builder instance.
*/
- public ComputeJobRunnerBuilder jobDescriptor(JobDescriptor jobDescriptor) {
+ public ComputeJobRunnerBuilder<T, R> jobDescriptor(JobDescriptor<T, R> jobDescriptor) {
this.jobDescriptor = jobDescriptor;
return this;
}
@@ -141,7 +140,7 @@ public class MapReduceJob {
* @param args Arguments of the job.
* @return Builder instance.
*/
- public ComputeJobRunnerBuilder args(Object... args) {
+ public ComputeJobRunnerBuilder<T, R> args(T args) {
this.args = args;
return this;
}
@@ -151,12 +150,12 @@ public class MapReduceJob {
*
* @return Description object.
*/
- public MapReduceJob build() {
+ public MapReduceJob<T, R> build() {
if (nodes.isEmpty()) {
throw new IllegalArgumentException();
}
- return new MapReduceJob(nodes, jobDescriptor, args);
+ return new MapReduceJob<>(nodes, jobDescriptor, args);
}
}
}
diff --git a/modules/api/src/main/java/org/apache/ignite/compute/task/MapReduceTask.java b/modules/api/src/main/java/org/apache/ignite/compute/task/MapReduceTask.java
index 3c547ec2e2..1f379ac030 100644
--- a/modules/api/src/main/java/org/apache/ignite/compute/task/MapReduceTask.java
+++ b/modules/api/src/main/java/org/apache/ignite/compute/task/MapReduceTask.java
@@ -21,32 +21,36 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
+import org.jetbrains.annotations.Nullable;
/**
* A map reduce task interface. Implement this interface and pass a name of the implemented class to the
- * {@link org.apache.ignite.compute.IgniteCompute#submitMapReduce(List, String, Object...) IgniteCompute#submitMapReduce} method to run this
+ * {@link org.apache.ignite.compute.IgniteCompute#submitMapReduce(List, String, Object) IgniteCompute#submitMapReduce} method to run this
* task.
*
- * @param <R> Result type.
+ * @param <I> Split task (I)nput type.
+ * @param <M> (M)ap job input type.
+ * @param <T> Map job output (T)ype and reduce job input (T)ype.
+ * @param <R> Reduce (R)esult type.
*/
-public interface MapReduceTask<R> {
+public interface MapReduceTask<I, M, T, R> {
/**
* This method should return a list of compute job execution parameters which will be used to submit compute jobs.
*
* @param taskContext Task execution context.
- * @param args Map reduce task arguments.
+ * @param input Map reduce task (I)nput.
* @return A future with the list of compute job execution parameters.
*/
- CompletableFuture<List<MapReduceJob>> splitAsync(TaskExecutionContext taskContext, Object... args);
+ CompletableFuture<List<MapReduceJob<M, T>>> splitAsync(TaskExecutionContext taskContext, @Nullable I input);
/**
* This is a finishing step in the task execution. This method will be called with the map from identifiers of compute jobs submitted as
- * a result of the {@link #splitAsync(TaskExecutionContext, Object...)} method call to the results of the execution of the corresponding
+ * a result of the {@link #splitAsync(TaskExecutionContext, Object)} method call to the results of the execution of the corresponding
* job. The return value of this method will be returned as a result of this task.
*
* @param taskContext Task execution context.
* @param results Map from compute job ids to their results.
* @return Final task result future.
*/
- CompletableFuture<R> reduceAsync(TaskExecutionContext taskContext, Map<UUID, ?> results);
+ CompletableFuture<R> reduceAsync(TaskExecutionContext taskContext, Map<UUID, T> results);
}
diff --git a/modules/api/src/main/java/org/apache/ignite/lang/ErrorGroups.java b/modules/api/src/main/java/org/apache/ignite/lang/ErrorGroups.java
index befa765114..b967b44857 100755
--- a/modules/api/src/main/java/org/apache/ignite/lang/ErrorGroups.java
+++ b/modules/api/src/main/java/org/apache/ignite/lang/ErrorGroups.java
@@ -49,8 +49,8 @@ public class ErrorGroups {
* @param groupName Group name to be created.
* @param groupCode Group code to be created.
* @return New error group.
- * @throws IllegalArgumentException If the specified name or group code already registered.
- * Also, this exception is thrown if the given {@code groupName} is {@code null} or empty.
+ * @throws IllegalArgumentException If the specified name or group code already registered. Also, this exception is thrown if
+ * the given {@code groupName} is {@code null} or empty.
*/
public static synchronized ErrorGroup registerGroup(String groupName, short groupCode) {
if (groupName == null || groupName.isEmpty()) {
@@ -149,8 +149,8 @@ public class ErrorGroups {
public static final int NULLABLE_VALUE_ERR = COMMON_ERR_GROUP.registerErrorCode((short) 9);
/**
- * This error code represents an internal error caused by faulty logic or coding in the Ignite codebase.
- * In general, this error code should be considered as a non-recoverable error
+ * This error code represents an internal error caused by faulty logic or coding in the Ignite codebase. In general, this error code
+ * should be considered as a non-recoverable error
*/
public static final int INTERNAL_ERR = COMMON_ERR_GROUP.registerErrorCode((short) 0xFFFF);
}
@@ -239,8 +239,8 @@ public class ErrorGroups {
public static final int STMT_PARSE_ERR = SQL_ERR_GROUP.registerErrorCode((short) 3);
/**
- * Statement validation error. Although statement is grammatically correct, the semantic is in question.
- * This error may appear in following cases:
+ * Statement validation error. Although statement is grammatically correct, the semantic is in question. This error may appear in
+ * following cases:
* <ul>
* <li>the statement refer to relation that doesn't exists.</li>
* <li>the statement describes action that is prohibited by the system, like changing columns belonging to primary keys.</li>
@@ -652,4 +652,17 @@ public class ErrorGroups {
/** Node start failed.. */
public static final int NODE_START_ERR = EMBEDDED_ERR_GROUP.registerErrorCode((short) 4);
}
+
+ /** Marshalling error group. */
+ @ErrorCodeGroup
+ public static class Marshalling {
+ /** Marshalling error group. */
+ public static final ErrorGroup MARSHALLING_ERR_GROUP = registerGroup("MARSHALLING", (short) 22);
+
+ /** Marshalling error. */
+ public static final int COMMON_ERR = MARSHALLING_ERR_GROUP.registerErrorCode((short) 1);
+
+ /** Unsupported object type error. */
+ public static final int UNSUPPORTED_OBJECT_TYPE_ERR = MARSHALLING_ERR_GROUP.registerErrorCode((short) 2);
+ }
}
diff --git a/modules/api/src/main/java/org/apache/ignite/marshaling/ByteArrayMarshaler.java b/modules/api/src/main/java/org/apache/ignite/marshaling/ByteArrayMarshaler.java
new file mode 100644
index 0000000000..bdebd5691b
--- /dev/null
+++ b/modules/api/src/main/java/org/apache/ignite/marshaling/ByteArrayMarshaler.java
@@ -0,0 +1,56 @@
+/*
+ * 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.marshaling;
+
+import java.io.Serializable;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * The ByteArrayMarshaler interface is designed to marshal and unmarshal objects to and from byte arrays. If the byte[] is your preferred
+ * way of marshaling objects, you can implement this interface to provide custom marshaling logic.
+ *
+ * <p>The default implementation of the marshal method is plain java serialization.
+ */
+public interface ByteArrayMarshaler<T> extends Marshaler<T, byte[]> {
+
+ static <T> ByteArrayMarshaler<T> create() {
+ return new ByteArrayMarshaler<>() {};
+ }
+
+ @Override
+ default byte @Nullable [] marshal(@Nullable T object) {
+ if (object == null) {
+ return null;
+ }
+
+ if (object instanceof Serializable) {
+ return JavaSerializationByteArrayMarshallilng.marshal((Serializable) object);
+ }
+
+ throw new UnsupportedObjectTypeMarshalingException(object.getClass());
+ }
+
+ @Override
+ default @Nullable T unmarshal(byte @Nullable [] raw) {
+ if (raw == null) {
+ return null;
+ }
+
+ return JavaSerializationByteArrayMarshallilng.unmarshal(raw);
+ }
+}
diff --git a/modules/api/src/main/java/org/apache/ignite/marshaling/JavaSerializationByteArrayMarshallilng.java b/modules/api/src/main/java/org/apache/ignite/marshaling/JavaSerializationByteArrayMarshallilng.java
new file mode 100644
index 0000000000..73e892d9b9
--- /dev/null
+++ b/modules/api/src/main/java/org/apache/ignite/marshaling/JavaSerializationByteArrayMarshallilng.java
@@ -0,0 +1,70 @@
+/*
+ * 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.marshaling;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Default java serialization marshaller. It is used by default if no other marshaller is provided.
+ */
+class JavaSerializationByteArrayMarshallilng {
+ /**
+ * Writes the object to a byte array with java serialization.
+ *
+ * @param <T> object.
+ * @return byte array that represents the object.
+ */
+ public static <T extends Serializable> byte @Nullable [] marshal(T object) {
+ if (object == null) {
+ return null;
+ }
+
+ try (var baos = new ByteArrayOutputStream(); var out = new ObjectOutputStream(baos)) {
+ out.writeObject(object);
+ out.flush();
+
+ return baos.toByteArray();
+ } catch (IOException e) {
+ throw new MarshallingException(e);
+ }
+ }
+
+ /**
+ * Reads the object from a byte array with java serialization.
+ *
+ * @param raw byte array that represents the object.
+ * @return object.
+ */
+ public static <T> @Nullable T unmarshal(byte @Nullable [] raw) {
+ if (raw == null) {
+ return null;
+ }
+
+ try (var bais = new ByteArrayInputStream(raw); var ois = new ObjectInputStream(bais)) {
+ return (T) ois.readObject();
+ } catch (IOException | ClassNotFoundException e) {
+ throw new MarshallingException(e);
+ }
+ }
+}
diff --git a/modules/api/src/main/java/org/apache/ignite/marshaling/Marshaler.java b/modules/api/src/main/java/org/apache/ignite/marshaling/Marshaler.java
new file mode 100644
index 0000000000..88b7560c2d
--- /dev/null
+++ b/modules/api/src/main/java/org/apache/ignite/marshaling/Marshaler.java
@@ -0,0 +1,57 @@
+/*
+ * 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.marshaling;
+
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Object marshaler interface that is used in every Ignite API that requires
+ * serialization/deserialization of user objects. If you want to define the way
+ * your objects are serialized/deserialized, you can implement this interface
+ * and pass it to the API that requires it.
+ *
+ * <p>NOTE: The marshaler itself are not sent over the wire. This means that if you
+ * define a custom marshaller on the client, you must also define the marshaler
+ * on the server as well.
+ *
+ * @param <T> The object (T)ype.
+ * @param <R> The (R)aw type, for example, {@code byte[]} or {@link org.apache.ignite.table.Tuple}.
+ */
+public interface Marshaler<T, R> {
+ /**
+ * Marshal the object into raw type.
+ *
+ * @param object object to marshal.
+ *
+ * @return raw presentation of object.
+ * @throws UnsupportedObjectTypeMarshalingException if the given type can not be marshalled with current instance.
+ */
+ @Nullable R marshal(@Nullable T object) throws UnsupportedObjectTypeMarshalingException;
+
+ /**
+ * Unmarshal the raw type into object.
+ *
+ * @param raw raw presentation of object.
+ *
+ * @return object.
+ * @throws UnsupportedObjectTypeMarshalingException if the given type can not be unmarshalled with current instance.
+ */
+ @Nullable T unmarshal(@Nullable R raw) throws UnsupportedObjectTypeMarshalingException;
+}
+
diff --git a/modules/api/src/main/java/org/apache/ignite/marshaling/MarshallingException.java b/modules/api/src/main/java/org/apache/ignite/marshaling/MarshallingException.java
new file mode 100644
index 0000000000..a96c4e4427
--- /dev/null
+++ b/modules/api/src/main/java/org/apache/ignite/marshaling/MarshallingException.java
@@ -0,0 +1,50 @@
+/*
+ * 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.marshaling;
+
+import java.util.UUID;
+import org.apache.ignite.lang.ErrorGroups.Marshalling;
+import org.apache.ignite.lang.IgniteException;
+
+/**
+ * Exception thrown when an object type is not supported by the marshaler.
+ */
+public class MarshallingException extends IgniteException {
+ private static final long serialVersionUID = -4170221560474770629L;
+
+ /**
+ * Creates an exception with the given unsupported type.
+ *
+ * @param exception The exception that caused the error.
+ */
+ MarshallingException(Exception exception) {
+ super(Marshalling.COMMON_ERR, exception);
+ }
+
+ /**
+ * Creates an exception with the given trace ID, error code, detailed message, and cause.
+ *
+ * @param traceId Unique identifier of the exception.
+ * @param code Full error code.
+ * @param message Detailed message.
+ * @param cause Optional nested exception (can be {@code null}).
+ */
+ public MarshallingException(UUID traceId, int code, String message, Throwable cause) {
+ super(traceId, code, message, cause);
+ }
+}
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/JobSubmitter.java b/modules/api/src/main/java/org/apache/ignite/marshaling/TupleMarshaller.java
similarity index 65%
copy from modules/compute/src/main/java/org/apache/ignite/internal/compute/task/JobSubmitter.java
copy to modules/api/src/main/java/org/apache/ignite/marshaling/TupleMarshaller.java
index 5f5c98829f..e6b2ad9d3a 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/JobSubmitter.java
+++ b/modules/api/src/main/java/org/apache/ignite/marshaling/TupleMarshaller.java
@@ -15,20 +15,17 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.compute.task;
+package org.apache.ignite.marshaling;
-import org.apache.ignite.compute.JobExecution;
-import org.apache.ignite.compute.task.MapReduceJob;
+import org.apache.ignite.table.Tuple;
/**
- * Compute job submitter.
+ * Ignite serialization protocol that can be used used instead of {@link ByteArrayMarshaler}.
*/
-@FunctionalInterface
-public interface JobSubmitter {
- /**
- * Submits compute job for an execution.
- *
- * @param computeJobRunner Computer job start parameters.
- */
- JobExecution<Object> submit(MapReduceJob computeJobRunner);
+interface TupleMarshaller<T> extends Marshaler<T, Tuple> {
+ @Override
+ Tuple marshal(T object);
+
+ @Override
+ T unmarshal(Tuple raw);
}
diff --git a/modules/api/src/main/java/org/apache/ignite/marshaling/UnsupportedObjectTypeMarshalingException.java b/modules/api/src/main/java/org/apache/ignite/marshaling/UnsupportedObjectTypeMarshalingException.java
new file mode 100644
index 0000000000..72248a9105
--- /dev/null
+++ b/modules/api/src/main/java/org/apache/ignite/marshaling/UnsupportedObjectTypeMarshalingException.java
@@ -0,0 +1,53 @@
+/*
+ * 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.marshaling;
+
+import java.util.UUID;
+import org.apache.ignite.lang.ErrorGroups.Marshalling;
+import org.apache.ignite.lang.IgniteException;
+
+/**
+ * Exception thrown when an object type is not supported by the marshaler.
+ */
+public class UnsupportedObjectTypeMarshalingException extends IgniteException {
+ private static final long serialVersionUID = -8131613381875542450L;
+
+ /**
+ * Creates an exception with the given unsupported type.
+ *
+ * @param unsupportedType Unsupported type.
+ */
+ UnsupportedObjectTypeMarshalingException(Class<?> unsupportedType) {
+ super(
+ Marshalling.UNSUPPORTED_OBJECT_TYPE_ERR,
+ "Unsupported object type: " + unsupportedType.getName() + ". Please, define the marshaler that can handle this type."
+ );
+ }
+
+ /**
+ * Creates an exception with the given trace ID, error code, detailed message, and cause.
+ *
+ * @param traceId Unique identifier of the exception.
+ * @param code Full error code.
+ * @param message Detailed message.
+ * @param cause Optional nested exception (can be {@code null}).
+ */
+ public UnsupportedObjectTypeMarshalingException(UUID traceId, int code, String message, Throwable cause) {
+ super(traceId, code, message, cause);
+ }
+}
diff --git a/modules/api/src/main/java/org/apache/ignite/table/DataStreamerReceiver.java b/modules/api/src/main/java/org/apache/ignite/table/DataStreamerReceiver.java
index 354fc2ae4c..883285d76e 100644
--- a/modules/api/src/main/java/org/apache/ignite/table/DataStreamerReceiver.java
+++ b/modules/api/src/main/java/org/apache/ignite/table/DataStreamerReceiver.java
@@ -29,23 +29,24 @@ import org.jetbrains.annotations.Nullable;
*
* @param <T> Payload type.
* @param <R> Result type.
+ * @param <A> Receiver job argument type.
*/
@SuppressWarnings("InterfaceMayBeAnnotatedFunctional")
-public interface DataStreamerReceiver<T, R> {
+public interface DataStreamerReceiver<T, A, R> {
/**
* Receives an item from the data streamer (see {@link DataStreamerTarget#streamData(Publisher, Function, Function,
- * ReceiverDescriptor, Subscriber, DataStreamerOptions, Object...)}).
+ * ReceiverDescriptor, Subscriber, DataStreamerOptions, Object)}).
*
* <p>The receiver is called for each page (batch) in the data streamer and is responsible for processing the items,
* updating zero or more tables, and returning a result.
*
* @param page Item batch.
* @param ctx Receiver context.
- * @param args Additional arguments.
+ * @param arg Additional argument.
* @return Future with the result. Null future for synchronous completion.
*/
@Nullable CompletableFuture<List<R>> receive(
List<T> page,
DataStreamerReceiverContext ctx,
- Object... args);
-}
\ No newline at end of file
+ A arg);
+}
diff --git a/modules/api/src/main/java/org/apache/ignite/table/DataStreamerTarget.java b/modules/api/src/main/java/org/apache/ignite/table/DataStreamerTarget.java
index 49507ae890..89e45e866f 100644
--- a/modules/api/src/main/java/org/apache/ignite/table/DataStreamerTarget.java
+++ b/modules/api/src/main/java/org/apache/ignite/table/DataStreamerTarget.java
@@ -49,18 +49,19 @@ public interface DataStreamerTarget<T> {
* NOTE: The result subscriber follows the pace of publisher and ignores backpressure
* from {@link Flow.Subscription#request(long)} calls.
* @param options Options (can be null).
- * @param receiverArgs Receiver arguments.
+ * @param receiverArg Receiver arguments.
* @return Future that will be completed when the stream is finished.
* @param <E> Producer item type.
* @param <V> Payload type.
* @param <R> Result type.
+ * @param <A> Receiver job argument type.
*/
- <E, V, R> CompletableFuture<Void> streamData(
+ <E, V, R, A> CompletableFuture<Void> streamData(
Flow.Publisher<E> publisher,
Function<E, T> keyFunc,
Function<E, V> payloadFunc,
- ReceiverDescriptor receiver,
+ ReceiverDescriptor<A> receiver,
@Nullable Flow.Subscriber<R> resultSubscriber,
@Nullable DataStreamerOptions options,
- Object... receiverArgs);
+ A receiverArg);
}
diff --git a/modules/api/src/main/java/org/apache/ignite/table/ReceiverDescriptor.java b/modules/api/src/main/java/org/apache/ignite/table/ReceiverDescriptor.java
index eef185ab10..4b80612a7a 100644
--- a/modules/api/src/main/java/org/apache/ignite/table/ReceiverDescriptor.java
+++ b/modules/api/src/main/java/org/apache/ignite/table/ReceiverDescriptor.java
@@ -20,21 +20,30 @@ package org.apache.ignite.table;
import java.util.List;
import java.util.Objects;
import org.apache.ignite.deployment.DeploymentUnit;
+import org.apache.ignite.marshaling.Marshaler;
+import org.jetbrains.annotations.Nullable;
/**
* Data streamer receiver descriptor.
*/
-public class ReceiverDescriptor {
+public class ReceiverDescriptor<A> {
private final String receiverClassName;
private final List<DeploymentUnit> units;
- private ReceiverDescriptor(String receiverClassName, List<DeploymentUnit> units) {
+ private final @Nullable Marshaler<A, byte[]> argumentsMarshaler;
+
+ private ReceiverDescriptor(
+ String receiverClassName,
+ List<DeploymentUnit> units,
+ @Nullable Marshaler<A, byte[]> argumentsMarshaler
+ ) {
Objects.requireNonNull(receiverClassName);
Objects.requireNonNull(units);
this.receiverClassName = receiverClassName;
this.units = units;
+ this.argumentsMarshaler = argumentsMarshaler;
}
/**
@@ -60,10 +69,10 @@ public class ReceiverDescriptor {
*
* @return Receiver descriptor builder.
*/
- public static Builder builder(String receiverClassName) {
+ public static <A> Builder<A> builder(String receiverClassName) {
Objects.requireNonNull(receiverClassName);
- return new Builder(receiverClassName);
+ return new Builder<>(receiverClassName);
}
/**
@@ -71,18 +80,24 @@ public class ReceiverDescriptor {
*
* @return Receiver descriptor builder.
*/
- public static Builder builder(Class<? extends DataStreamerReceiver<?, ?>> receiverClass) {
+ public static <A> Builder<A> builder(Class<? extends DataStreamerReceiver<?, A, ?>> receiverClass) {
Objects.requireNonNull(receiverClass);
- return new Builder(receiverClass.getName());
+ return new Builder<>(receiverClass.getName());
+ }
+
+ public @Nullable Marshaler<A, byte[]> argumentsMarshaler() {
+ return argumentsMarshaler;
}
/**
* Builder.
*/
- public static class Builder {
+ public static class Builder<A> {
private final String receiverClassName;
private List<DeploymentUnit> units;
+ private @Nullable Marshaler<A, byte[]> argumentsMarshaller;
+
private Builder(String receiverClassName) {
Objects.requireNonNull(receiverClassName);
@@ -96,7 +111,7 @@ public class ReceiverDescriptor {
* @param units Deployment units.
* @return This builder.
*/
- public Builder units(List<DeploymentUnit> units) {
+ public Builder<A> units(List<DeploymentUnit> units) {
this.units = units;
return this;
}
@@ -107,20 +122,27 @@ public class ReceiverDescriptor {
* @param units Deployment units.
* @return This builder.
*/
- public Builder units(DeploymentUnit... units) {
+ public Builder<A> units(DeploymentUnit... units) {
this.units = List.of(units);
return this;
}
+ public Builder<A> argumentsMarshaler(@Nullable Marshaler<A, byte[]> argumentsMarshaller) {
+ this.argumentsMarshaller = argumentsMarshaller;
+ return this;
+ }
+
/**
* Builds the receiver descriptor.
*
* @return Receiver descriptor.
*/
- public ReceiverDescriptor build() {
- return new ReceiverDescriptor(
+ public ReceiverDescriptor<A> build() {
+ return new ReceiverDescriptor<>(
receiverClassName,
- units == null ? List.of() : units);
+ units == null ? List.of() : units,
+ argumentsMarshaller
+ );
}
}
}
diff --git a/modules/api/src/test/java/org/apache/ignite/marshaling/ByteArrayMarshalerTest.java b/modules/api/src/test/java/org/apache/ignite/marshaling/ByteArrayMarshalerTest.java
new file mode 100644
index 0000000000..c0e3637d14
--- /dev/null
+++ b/modules/api/src/test/java/org/apache/ignite/marshaling/ByteArrayMarshalerTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.marshaling;
+
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.Period;
+import java.util.BitSet;
+import java.util.UUID;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class ByteArrayMarshalerTest {
+
+ private static Stream<Arguments> primitiveTypes() {
+ return Stream.of(
+ Byte.valueOf("1"),
+ Short.valueOf("1"),
+ Integer.valueOf(1),
+ Long.valueOf(1),
+ Float.valueOf(1),
+ Double.valueOf(1),
+ Boolean.TRUE,
+ new BigDecimal(11),
+ new BigDecimal("11.1"),
+ UUID.randomUUID(),
+ "Hi, I am string",
+ new BitSet(1),
+ LocalDate.now(),
+ LocalDateTime.now(),
+ Timestamp.valueOf(LocalDateTime.now()),
+ Duration.ofDays(1),
+ Period.ofMonths(1)
+ ).map(Arguments::of);
+ }
+
+ private static Stream<Arguments> cornerValues() {
+ return Stream.of(
+ "", ".*456+576+$%^&*()_+{}|:<>?`~", "1", "0",
+ -1, 0,
+ new Object()
+ ).map(Arguments::of);
+ }
+
+ @ParameterizedTest
+ @MethodSource("primitiveTypes")
+ void marshalPrimitiveTypes(Object obj) {
+ ByteArrayMarshaler<Object> marshaler = ByteArrayMarshaler.create();
+
+ assertEquals(obj, marshaler.unmarshal(marshaler.marshal(obj)));
+ }
+
+ @Test
+ void nullValue() {
+ ByteArrayMarshaler<Object> marshaler = ByteArrayMarshaler.create();
+ assertNull(marshaler.unmarshal(marshaler.marshal(null)));
+ }
+
+ @ParameterizedTest
+ @MethodSource("cornerValues")
+ void cornerValuesMarshalling(Object obj) {
+
+ }
+
+
+ @Test
+ void byteArray() {
+ ByteArrayMarshaler<byte[]> marshaler = ByteArrayMarshaler.create();
+
+ byte[] bytes = {1, 2, 3, 4, 5};
+
+ assertArrayEquals(bytes, marshaler.unmarshal(marshaler.marshal(bytes)));
+ }
+
+ @Test
+ void javaInt() {
+ ByteArrayMarshaler<Integer> intMarshaller = ByteArrayMarshaler.create();
+ assertEquals(2, intMarshaller.unmarshal(intMarshaller.marshal(2)));
+ }
+
+ @Test
+ void javaString() {
+ ByteArrayMarshaler<String> stringMarshaller = ByteArrayMarshaler.create();
+ assertEquals("Hello", stringMarshaller.unmarshal(stringMarshaller.marshal("Hello")));
+ }
+
+ @Test
+ void javaBoolean() {
+ ByteArrayMarshaler<Boolean> booleanMarshaller = ByteArrayMarshaler.create();
+ assertEquals(true, booleanMarshaller.unmarshal(booleanMarshaller.marshal(true)));
+ }
+
+ @Test
+ void javaLong() {
+ ByteArrayMarshaler<Long> longMarshaller = ByteArrayMarshaler.create();
+ assertEquals(2L, longMarshaller.unmarshal(longMarshaller.marshal(2L)));
+ }
+
+ @Test
+ void javaShort() {
+ ByteArrayMarshaler<Short> shortMarshaller = ByteArrayMarshaler.create();
+ assertEquals((short) 2, shortMarshaller.unmarshal(shortMarshaller.marshal((short) 2)));
+ }
+
+ @Test
+ void javaByte() {
+ ByteArrayMarshaler<Byte> byteMarshaller = ByteArrayMarshaler.create();
+ assertEquals((byte) 2, byteMarshaller.unmarshal(byteMarshaller.marshal((byte) 2)));
+ }
+
+ @Test
+ void javaFloat() {
+ ByteArrayMarshaler<Float> floatMarshaller = ByteArrayMarshaler.create();
+ assertEquals(2.0f, floatMarshaller.unmarshal(floatMarshaller.marshal(2.0f)));
+ }
+
+ @Test
+ void notSerializable() {
+ ByteArrayMarshaler<NotSerializable> notSerializableMarshaller = ByteArrayMarshaler.create();
+
+ NotSerializable notSerializable = new NotSerializable(2);
+
+ assertThrows(
+ UnsupportedObjectTypeMarshalingException.class,
+ () -> notSerializableMarshaller.marshal(notSerializable)
+ );
+ }
+
+ private static class NotSerializable {
+ private final int value;
+
+ private NotSerializable(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+ }
+}
diff --git a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientBinaryTupleUtils.java b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientBinaryTupleUtils.java
index 79cb4c52e2..baefc3d802 100644
--- a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientBinaryTupleUtils.java
+++ b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientBinaryTupleUtils.java
@@ -38,6 +38,7 @@ import java.util.function.Function;
import org.apache.ignite.internal.binarytuple.BinaryTupleBuilder;
import org.apache.ignite.internal.binarytuple.BinaryTupleReader;
import org.apache.ignite.lang.IgniteException;
+import org.apache.ignite.marshaling.Marshaler;
import org.apache.ignite.sql.ColumnType;
import org.jetbrains.annotations.Nullable;
@@ -49,7 +50,7 @@ public class ClientBinaryTupleUtils {
* Reads an object from binary tuple at the specified index.
*
* @param reader Binary tuple reader.
- * @param index Starting index in the binary tuple.
+ * @param index Starting index in the binary tuple.
* @return Object.
*/
static @Nullable Object readObject(BinaryTupleReader reader, int index) {
@@ -194,11 +195,14 @@ public class ClientBinaryTupleUtils {
* @param builder Builder.
* @param obj Object.
*/
- public static void appendObject(BinaryTupleBuilder builder, Object obj) {
+ public static <T> void appendObject(BinaryTupleBuilder builder, T obj, @Nullable Marshaler<T, byte[]> marshaler) {
if (obj == null) {
builder.appendNull(); // Type.
builder.appendNull(); // Scale.
builder.appendNull(); // Value.
+ } else if (marshaler != null) {
+ appendTypeAndScale(builder, ColumnType.BYTE_ARRAY);
+ builder.appendBytes(marshaler.marshal(obj));
} else if (obj instanceof Boolean) {
appendTypeAndScale(builder, ColumnType.BOOLEAN);
builder.appendBoolean((Boolean) obj);
diff --git a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessagePacker.java b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessagePacker.java
index c94b182fb4..7d6aca3d36 100644
--- a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessagePacker.java
+++ b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessagePacker.java
@@ -30,6 +30,7 @@ import java.util.UUID;
import org.apache.ignite.deployment.DeploymentUnit;
import org.apache.ignite.internal.binarytuple.BinaryTupleBuilder;
import org.apache.ignite.internal.binarytuple.BinaryTupleParser;
+import org.apache.ignite.marshaling.Marshaler;
import org.apache.ignite.sql.BatchedArguments;
import org.jetbrains.annotations.Nullable;
@@ -598,7 +599,7 @@ public class ClientMessagePacker implements AutoCloseable {
*
* @param vals Object array.
*/
- public void packObjectArrayAsBinaryTuple(Object @Nullable [] vals) {
+ public void packObjectArrayAsBinaryTuple(Object @Nullable [] vals, @Nullable Marshaler<Object, byte[]> marshaller) {
assert !closed : "Packer is closed";
if (vals == null) {
@@ -618,7 +619,7 @@ public class ClientMessagePacker implements AutoCloseable {
var builder = new BinaryTupleBuilder(vals.length * 3);
for (Object arg : vals) {
- ClientBinaryTupleUtils.appendObject(builder, arg);
+ ClientBinaryTupleUtils.appendObject(builder, arg, marshaller);
}
packBinaryTuple(builder);
@@ -650,7 +651,7 @@ public class ClientMessagePacker implements AutoCloseable {
var builder = new BinaryTupleBuilder(rowLen * 3);
for (Object value : values) {
- ClientBinaryTupleUtils.appendObject(builder, value);
+ ClientBinaryTupleUtils.appendObject(builder, value, null);
}
packBinaryTuple(builder);
@@ -662,7 +663,7 @@ public class ClientMessagePacker implements AutoCloseable {
*
* @param val Object array.
*/
- public void packObjectAsBinaryTuple(Object val) {
+ public <T> void packObjectAsBinaryTuple(T val, @Nullable Marshaler<T, byte[]> marshaler) {
assert !closed : "Packer is closed";
if (val == null) {
@@ -673,8 +674,8 @@ public class ClientMessagePacker implements AutoCloseable {
// Builder with inline schema.
// Value is represented by 3 tuple elements: type, scale, value.
- var builder = new BinaryTupleBuilder(3, 3);
- ClientBinaryTupleUtils.appendObject(builder, val);
+ var builder = new BinaryTupleBuilder(3, 3, false);
+ ClientBinaryTupleUtils.appendObject(builder, val, marshaler);
packBinaryTuple(builder);
}
diff --git a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessageUnpacker.java b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessageUnpacker.java
index 234dfadc83..2080c84f99 100644
--- a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessageUnpacker.java
+++ b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessageUnpacker.java
@@ -486,6 +486,17 @@ public class ClientMessageUnpacker implements AutoCloseable {
return res;
}
+ /**
+ * Reads a payload into the specified buffer.
+ *
+ * @param target Target buffer.
+ */
+ public void readPayload(ByteBuffer target) {
+ assert refCnt > 0 : "Unpacker is closed";
+
+ buf.readBytes(target);
+ }
+
/**
* Reads a binary value.
*
diff --git a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/StreamerReceiverSerializer.java b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/StreamerReceiverSerializer.java
index 8f00e19afa..4644de3ef8 100644
--- a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/StreamerReceiverSerializer.java
+++ b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/StreamerReceiverSerializer.java
@@ -19,11 +19,13 @@ package org.apache.ignite.internal.client.proto;
import static org.apache.ignite.lang.ErrorGroups.Client.PROTOCOL_ERR;
+import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.List;
import org.apache.ignite.internal.binarytuple.BinaryTupleBuilder;
import org.apache.ignite.internal.binarytuple.BinaryTupleReader;
import org.apache.ignite.lang.IgniteException;
+import org.apache.ignite.marshaling.Marshaler;
import org.jetbrains.annotations.Nullable;
/**
@@ -38,16 +40,14 @@ public class StreamerReceiverSerializer {
* @param receiverArgs Receiver arguments.
* @param items Items.
*/
- public static void serialize(ClientMessagePacker w, String receiverClassName, Object[] receiverArgs, Collection<?> items) {
- // className + args size + args + items size + item type + items.
- int binaryTupleSize = 1 + 1 + receiverArgs.length * 3 + 1 + 1 + items.size();
+ public static <A> void serialize(ClientMessagePacker w, String receiverClassName, A receiverArgs,
+ @Nullable Marshaler<A, byte[]> receiverArgsMarshaler, Collection<?> items) {
+ // className + arg + items size + item type + items.
+ int binaryTupleSize = 1 + 3 + 1 + 1 + items.size();
var builder = new BinaryTupleBuilder(binaryTupleSize);
builder.appendString(receiverClassName);
- builder.appendInt(receiverArgs.length);
- for (var arg : receiverArgs) {
- ClientBinaryTupleUtils.appendObject(builder, arg);
- }
+ ClientBinaryTupleUtils.appendObject(builder, receiverArgs, receiverArgsMarshaler);
ClientBinaryTupleUtils.appendCollectionToBinaryTuple(builder, items);
@@ -62,7 +62,7 @@ public class StreamerReceiverSerializer {
* @param elementCount Number of elements in the binary tuple.
* @return Streamer receiver info.
*/
- public static SteamerReceiverInfo deserialize(byte[] bytes, int elementCount) {
+ public static SteamerReceiverInfo deserialize(ByteBuffer bytes, int elementCount) {
var reader = new BinaryTupleReader(elementCount, bytes);
int readerIndex = 0;
@@ -72,13 +72,9 @@ public class StreamerReceiverSerializer {
throw new IgniteException(PROTOCOL_ERR, "Receiver class name is null");
}
- int receiverArgsCount = reader.intValue(readerIndex++);
+ Object receiverArgs = ClientBinaryTupleUtils.readObject(reader, readerIndex);
- Object[] receiverArgs = new Object[receiverArgsCount];
- for (int i = 0; i < receiverArgsCount; i++) {
- receiverArgs[i] = ClientBinaryTupleUtils.readObject(reader, readerIndex);
- readerIndex += 3;
- }
+ readerIndex += 3;
List<Object> items = ClientBinaryTupleUtils.readCollectionFromBinaryTuple(reader, readerIndex);
@@ -128,10 +124,10 @@ public class StreamerReceiverSerializer {
*/
public static class SteamerReceiverInfo {
private final String className;
- private final Object[] args;
+ private final Object args;
private final List<Object> items;
- private SteamerReceiverInfo(String className, Object[] args, List<Object> items) {
+ private SteamerReceiverInfo(String className, Object args, List<Object> items) {
this.className = className;
this.args = args;
this.items = items;
@@ -151,7 +147,7 @@ public class StreamerReceiverSerializer {
*
* @return Receiver args.
*/
- public Object[] args() {
+ public Object args() {
return args;
}
diff --git a/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/event/JdbcBatchPreparedStmntRequest.java b/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/event/JdbcBatchPreparedStmntRequest.java
index 46f5509ff8..5aa27342f2 100644
--- a/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/event/JdbcBatchPreparedStmntRequest.java
+++ b/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/event/JdbcBatchPreparedStmntRequest.java
@@ -132,7 +132,7 @@ public class JdbcBatchPreparedStmntRequest implements ClientMessage {
packer.packInt(args.size());
for (Object[] arg : args) {
- packer.packObjectArrayAsBinaryTuple(arg);
+ packer.packObjectArrayAsBinaryTuple(arg, null);
}
packer.packLong(queryTimeoutMillis);
diff --git a/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/event/JdbcQueryExecuteRequest.java b/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/event/JdbcQueryExecuteRequest.java
index 4a521b0e7c..56159b5c94 100644
--- a/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/event/JdbcQueryExecuteRequest.java
+++ b/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/event/JdbcQueryExecuteRequest.java
@@ -79,10 +79,10 @@ public class JdbcQueryExecuteRequest implements ClientMessage {
String schemaName,
int pageSize,
int maxRows,
- String sqlQry,
- Object[] args,
- boolean autoCommit,
- boolean multiStatement,
+ String sqlQry,
+ Object[] args,
+ boolean autoCommit,
+ boolean multiStatement,
long queryTimeoutMillis
) {
Objects.requireNonNull(stmtType);
@@ -188,7 +188,7 @@ public class JdbcQueryExecuteRequest implements ClientMessage {
packer.packString(sqlQry);
packer.packBoolean(multiStatement);
- packer.packObjectArrayAsBinaryTuple(args);
+ packer.packObjectArrayAsBinaryTuple(args, null);
packer.packLong(queryTimeoutMillis);
}
diff --git a/modules/client-common/src/test/java/org/apache/ignite/internal/client/proto/ClientMessagePackerUnpackerTest.java b/modules/client-common/src/test/java/org/apache/ignite/internal/client/proto/ClientMessagePackerUnpackerTest.java
index 9a9ccd497d..be9301c4a3 100644
--- a/modules/client-common/src/test/java/org/apache/ignite/internal/client/proto/ClientMessagePackerUnpackerTest.java
+++ b/modules/client-common/src/test/java/org/apache/ignite/internal/client/proto/ClientMessagePackerUnpackerTest.java
@@ -162,9 +162,9 @@ public class ClientMessagePackerUnpackerTest {
@Test
public void testObjectArrayAsBinaryTuple() {
try (var packer = new ClientMessagePacker(PooledByteBufAllocator.DEFAULT.directBuffer())) {
- packer.packObjectArrayAsBinaryTuple(argsAllTypes);
- packer.packObjectArrayAsBinaryTuple(null);
- packer.packObjectArrayAsBinaryTuple(new Object[0]);
+ packer.packObjectArrayAsBinaryTuple(argsAllTypes, null);
+ packer.packObjectArrayAsBinaryTuple(null, null);
+ packer.packObjectArrayAsBinaryTuple(new Object[0], null);
byte[] data = ByteBufUtil.getBytes(packer.getBuffer());
@@ -184,7 +184,7 @@ public class ClientMessagePackerUnpackerTest {
public void testObjectAsBinaryTuple() {
try (var packer = new ClientMessagePacker(PooledByteBufAllocator.DEFAULT.directBuffer())) {
for (Object arg : argsAllTypes) {
- packer.packObjectAsBinaryTuple(arg);
+ packer.packObjectAsBinaryTuple(arg, null);
}
byte[] data = ByteBufUtil.getBytes(packer.getBuffer());
diff --git a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteColocatedRequest.java b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteColocatedRequest.java
index cc931db448..83faf6bae3 100644
--- a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteColocatedRequest.java
+++ b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteColocatedRequest.java
@@ -18,7 +18,7 @@
package org.apache.ignite.client.handler.requests.compute;
import static org.apache.ignite.client.handler.requests.compute.ClientComputeExecuteRequest.sendResultAndState;
-import static org.apache.ignite.client.handler.requests.compute.ClientComputeExecuteRequest.unpackArgs;
+import static org.apache.ignite.client.handler.requests.compute.ClientComputeExecuteRequest.unpackPayload;
import static org.apache.ignite.client.handler.requests.table.ClientTableCommon.readTableAsync;
import static org.apache.ignite.client.handler.requests.table.ClientTableCommon.readTuple;
@@ -59,7 +59,7 @@ public class ClientComputeExecuteColocatedRequest {
List<DeploymentUnit> deploymentUnits = in.unpackDeploymentUnits();
String jobClassName = in.unpackString();
JobExecutionOptions options = JobExecutionOptions.builder().priority(in.unpackInt()).maxRetries(in.unpackInt()).build();
- Object[] args = unpackArgs(in);
+ Object args = unpackPayload(in);
out.packInt(table.schemaView().lastKnownSchemaVersion());
@@ -73,7 +73,7 @@ public class ClientComputeExecuteColocatedRequest {
var jobExecution = compute.wrapJobExecutionFuture(jobExecutionFut);
- sendResultAndState(jobExecution, notificationSender);
+ sendResultAndState(jobExecution, notificationSender, null);
//noinspection DataFlowIssue
return jobExecution.idAsync().thenAccept(out::packUuid);
diff --git a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteMapReduceRequest.java b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteMapReduceRequest.java
index a2ea6396b7..c79b867fc4 100644
--- a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteMapReduceRequest.java
+++ b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteMapReduceRequest.java
@@ -17,7 +17,7 @@
package org.apache.ignite.client.handler.requests.compute;
-import static org.apache.ignite.client.handler.requests.compute.ClientComputeExecuteRequest.unpackArgs;
+import static org.apache.ignite.client.handler.requests.compute.ClientComputeExecuteRequest.unpackPayload;
import static org.apache.ignite.client.handler.requests.compute.ClientComputeGetStateRequest.packJobState;
import static org.apache.ignite.client.handler.requests.compute.ClientComputeGetStateRequest.packTaskState;
import static org.apache.ignite.internal.util.IgniteUtils.firstNotNull;
@@ -54,7 +54,7 @@ public class ClientComputeExecuteMapReduceRequest {
NotificationSender notificationSender) {
List<DeploymentUnit> deploymentUnits = in.unpackDeploymentUnits();
String taskClassName = in.unpackString();
- Object[] args = unpackArgs(in);
+ Object args = unpackPayload(in);
TaskExecution<Object> execution = compute.submitMapReduce(deploymentUnits, taskClassName, args);
sendTaskResult(execution, notificationSender);
@@ -84,7 +84,7 @@ public class ClientComputeExecuteMapReduceRequest {
execution.stateAsync().whenComplete((state, errState) ->
execution.statesAsync().whenComplete((states, errStates) ->
notificationSender.sendNotification(w -> {
- w.packObjectAsBinaryTuple(val);
+ w.packObjectAsBinaryTuple(val, null);
packTaskState(w, state);
packJobStates(w, states);
}, firstNotNull(err, errState, errStates)))
diff --git a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteRequest.java b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteRequest.java
index 8007ebadae..8f5a2c3267 100644
--- a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteRequest.java
+++ b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/compute/ClientComputeExecuteRequest.java
@@ -32,6 +32,7 @@ import org.apache.ignite.internal.client.proto.ClientMessagePacker;
import org.apache.ignite.internal.client.proto.ClientMessageUnpacker;
import org.apache.ignite.internal.compute.IgniteComputeInternal;
import org.apache.ignite.internal.network.ClusterService;
+import org.apache.ignite.marshaling.Marshaler;
import org.apache.ignite.network.ClusterNode;
/**
@@ -60,10 +61,10 @@ public class ClientComputeExecuteRequest {
List<DeploymentUnit> deploymentUnits = in.unpackDeploymentUnits();
String jobClassName = in.unpackString();
JobExecutionOptions options = JobExecutionOptions.builder().priority(in.unpackInt()).maxRetries(in.unpackInt()).build();
- Object[] args = unpackArgs(in);
+ Object arg = unpackPayload(in);
- JobExecution<Object> execution = compute.executeAsyncWithFailover(candidates, deploymentUnits, jobClassName, options, args);
- sendResultAndState(execution, notificationSender);
+ JobExecution<Object> execution = compute.executeAsyncWithFailover(candidates, deploymentUnits, jobClassName, options, arg);
+ sendResultAndState(execution, notificationSender, null);
//noinspection DataFlowIssue
return execution.idAsync().thenAccept(out::packUuid);
@@ -95,11 +96,15 @@ public class ClientComputeExecuteRequest {
return nodes;
}
- static CompletableFuture<Object> sendResultAndState(JobExecution<Object> execution, NotificationSender notificationSender) {
+ static CompletableFuture<Object> sendResultAndState(
+ JobExecution<Object> execution,
+ NotificationSender notificationSender,
+ Marshaler<Object, byte[]> marshaler
+ ) {
return execution.resultAsync().whenComplete((val, err) ->
execution.stateAsync().whenComplete((state, errState) ->
notificationSender.sendNotification(w -> {
- w.packObjectAsBinaryTuple(val);
+ w.packObjectAsBinaryTuple(val, marshaler);
packJobState(w, state);
}, err)));
}
@@ -110,7 +115,7 @@ public class ClientComputeExecuteRequest {
* @param in Unpacker.
* @return Args array.
*/
- static Object[] unpackArgs(ClientMessageUnpacker in) {
- return in.unpackObjectArrayFromBinaryTuple();
+ static Object unpackPayload(ClientMessageUnpacker in) {
+ return in.unpackObjectFromBinaryTuple();
}
}
diff --git a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/table/ClientStreamerWithReceiverBatchSendRequest.java b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/table/ClientStreamerWithReceiverBatchSendRequest.java
index d9a0e2b474..14d215bffa 100644
--- a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/table/ClientStreamerWithReceiverBatchSendRequest.java
+++ b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/table/ClientStreamerWithReceiverBatchSendRequest.java
@@ -20,6 +20,8 @@ package org.apache.ignite.client.handler.requests.table;
import static org.apache.ignite.client.handler.requests.table.ClientTableCommon.readTableAsync;
import static org.apache.ignite.lang.ErrorGroups.Compute.COMPUTE_JOB_FAILED_ERR;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@@ -50,9 +52,9 @@ public class ClientStreamerWithReceiverBatchSendRequest {
/**
* Processes the request.
*
- * @param in Unpacker.
- * @param out Packer.
- * @param tables Ignite tables.
+ * @param in Unpacker.
+ * @param out Packer.
+ * @param tables Ignite tables.
* @return Future.
*/
public static CompletableFuture<Void> process(
@@ -68,7 +70,13 @@ public class ClientStreamerWithReceiverBatchSendRequest {
// Payload = binary tuple of (receiverClassName, receiverArgs, items). We pass it to the job without deserialization.
int payloadElementCount = in.unpackInt();
- byte[] payload = in.readBinary();
+ int payloadSize = in.unpackBinaryHeader();
+
+ byte[] payloadArr = new byte[payloadSize + 4];
+ var payloadBuf = ByteBuffer.wrap(payloadArr).order(ByteOrder.LITTLE_ENDIAN);
+
+ payloadBuf.putInt(payloadElementCount);
+ in.readPayload(payloadBuf);
return table.partitionManager().primaryReplicaAsync(new HashPartition(partition)).thenCompose(primaryReplica -> {
// Use Compute to execute receiver on the target node with failover, class loading, scheduling.
@@ -77,8 +85,7 @@ public class ClientStreamerWithReceiverBatchSendRequest {
deploymentUnits,
ReceiverRunnerJob.class.getName(),
JobExecutionOptions.DEFAULT,
- payloadElementCount,
- payload);
+ payloadArr);
return jobExecution.resultAsync()
.handle((res, err) -> {
@@ -100,17 +107,19 @@ public class ClientStreamerWithReceiverBatchSendRequest {
});
}
- private static class ReceiverRunnerJob implements ComputeJob<List<Object>> {
+ private static class ReceiverRunnerJob implements ComputeJob<byte[], List<Object>> {
@Override
- public @Nullable CompletableFuture<List<Object>> executeAsync(JobExecutionContext context, Object... args) {
- int payloadElementCount = (int) args[0];
- byte[] payload = (byte[]) args[1];
+ public @Nullable CompletableFuture<List<Object>> executeAsync(JobExecutionContext context, byte[] payload) {
+ ByteBuffer buf = ByteBuffer.wrap(payload).order(ByteOrder.LITTLE_ENDIAN);
+ int payloadElementCount = buf.getInt();
- var receiverInfo = StreamerReceiverSerializer.deserialize(payload, payloadElementCount);
+ var receiverInfo = StreamerReceiverSerializer.deserialize(buf.slice().order(ByteOrder.LITTLE_ENDIAN), payloadElementCount);
ClassLoader classLoader = ((JobExecutionContextImpl) context).classLoader();
- Class<DataStreamerReceiver<Object, Object>> receiverClass = ComputeUtils.receiverClass(classLoader, receiverInfo.className());
- DataStreamerReceiver<Object, Object> receiver = ComputeUtils.instantiateReceiver(receiverClass);
+ Class<DataStreamerReceiver<Object, Object, Object>> receiverClass = ComputeUtils.receiverClass(
+ classLoader, receiverInfo.className()
+ );
+ DataStreamerReceiver<Object, Object, Object> receiver = ComputeUtils.instantiateReceiver(receiverClass);
DataStreamerReceiverContext receiverContext = context::ignite;
return receiver.receive(receiverInfo.items(), receiverContext, receiverInfo.args());
diff --git a/modules/client/src/main/java/org/apache/ignite/client/ClientOperationType.java b/modules/client/src/main/java/org/apache/ignite/client/ClientOperationType.java
index 24d7627343..a5b37d8fe0 100644
--- a/modules/client/src/main/java/org/apache/ignite/client/ClientOperationType.java
+++ b/modules/client/src/main/java/org/apache/ignite/client/ClientOperationType.java
@@ -130,12 +130,12 @@ public enum ClientOperationType {
TUPLE_CONTAINS_KEY,
/**
- * Compute Execute ({@link org.apache.ignite.compute.IgniteCompute#submit(JobTarget, JobDescriptor, Object...)}).
+ * Compute Execute ({@link org.apache.ignite.compute.IgniteCompute#submit(JobTarget, JobDescriptor, Object)}).
*/
COMPUTE_EXECUTE,
/**
- * Compute Execute MapReduce ({@link org.apache.ignite.compute.IgniteCompute#submitMapReduce(List, String, Object...)}).
+ * Compute Execute MapReduce ({@link org.apache.ignite.compute.IgniteCompute#submitMapReduce(List, String, Object)}).
*/
COMPUTE_EXECUTE_MAPREDUCE,
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientCompute.java b/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientCompute.java
index 112e5a93e3..f3a9aab616 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientCompute.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientCompute.java
@@ -61,9 +61,11 @@ import org.apache.ignite.internal.sql.SqlCommon;
import org.apache.ignite.internal.util.ExceptionUtils;
import org.apache.ignite.lang.IgniteException;
import org.apache.ignite.lang.TableNotFoundException;
+import org.apache.ignite.marshaling.Marshaler;
import org.apache.ignite.network.ClusterNode;
import org.apache.ignite.table.Tuple;
import org.apache.ignite.table.mapper.Mapper;
+import org.jetbrains.annotations.Nullable;
/**
* Client compute implementation.
@@ -90,19 +92,24 @@ public class ClientCompute implements IgniteCompute {
}
@Override
- public <R> JobExecution<R> submit(JobTarget target, JobDescriptor descriptor, Object... args) {
+ public <T, R> JobExecution<R> submit(JobTarget target, JobDescriptor<T, R> descriptor, T arg) {
Objects.requireNonNull(target);
Objects.requireNonNull(descriptor);
if (target instanceof AnyNodeJobTarget) {
AnyNodeJobTarget anyNodeJobTarget = (AnyNodeJobTarget) target;
- return new ClientJobExecution<>(ch, executeOnAnyNodeAsync(
+ return new ClientJobExecution<>(
+ ch,
+ executeOnAnyNodeAsync(
anyNodeJobTarget.nodes(),
descriptor.units(),
descriptor.jobClassName(),
descriptor.options(),
- args));
+ descriptor.argumentMarshaler(),
+ arg),
+ descriptor.resultMarshaller()
+ );
}
if (target instanceof ColocatedJobTarget) {
@@ -110,22 +117,33 @@ public class ClientCompute implements IgniteCompute {
var mapper = (Mapper<? super Object>) colocatedTarget.keyMapper();
if (mapper != null) {
- return new ClientJobExecution<>(ch, doExecuteColocatedAsync(
+ return new ClientJobExecution<>(
+ ch,
+ doExecuteColocatedAsync(
colocatedTarget.tableName(),
colocatedTarget.key(),
mapper,
descriptor.units(),
descriptor.jobClassName(),
descriptor.options(),
- args));
+ descriptor.argumentMarshaler(),
+ arg
+ ),
+ descriptor.resultMarshaller());
} else {
- return new ClientJobExecution<>(ch, doExecuteColocatedAsync(
+ return new ClientJobExecution<>(
+ ch,
+ doExecuteColocatedAsync(
colocatedTarget.tableName(),
(Tuple) colocatedTarget.key(),
descriptor.units(),
descriptor.jobClassName(),
descriptor.options(),
- args));
+ descriptor.argumentMarshaler(),
+ arg
+ ),
+ descriptor.resultMarshaller()
+ );
}
}
@@ -133,55 +151,57 @@ public class ClientCompute implements IgniteCompute {
}
@Override
- public <R> R execute(JobTarget target, JobDescriptor descriptor, Object... args) {
+ public <T, R> R execute(JobTarget target, JobDescriptor<T, R> descriptor, T args) {
return sync(executeAsync(target, descriptor, args));
}
- private CompletableFuture<SubmitResult> doExecuteColocatedAsync(
+ private <T> CompletableFuture<SubmitResult> doExecuteColocatedAsync(
String tableName,
Tuple key,
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object... args
+ Marshaler<T, byte[]> marshaler,
+ T args
) {
return getTable(tableName)
- .thenCompose(table -> executeColocatedTupleKey(table, key, units, jobClassName, options, args))
+ .thenCompose(table -> executeColocatedTupleKey(table, key, units, jobClassName, options, marshaler, args))
.handle((res, err) -> handleMissingTable(
tableName,
res,
err,
- () -> doExecuteColocatedAsync(tableName, key, units, jobClassName, options, args)
+ () -> doExecuteColocatedAsync(tableName, key, units, jobClassName, options, marshaler, args)
))
.thenCompose(Function.identity());
}
- private <K> CompletableFuture<SubmitResult> doExecuteColocatedAsync(
+ private <K, T> CompletableFuture<SubmitResult> doExecuteColocatedAsync(
String tableName,
K key,
Mapper<K> keyMapper,
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object... args
+ Marshaler<T, byte[]> marshaler,
+ T args
) {
return getTable(tableName)
- .thenCompose(table -> executeColocatedObjectKey(table, key, keyMapper, units, jobClassName, options, args))
+ .thenCompose(table -> executeColocatedObjectKey(table, key, keyMapper, units, jobClassName, options, marshaler, args))
.handle((res, err) -> handleMissingTable(
tableName,
res,
err,
- () -> doExecuteColocatedAsync(tableName, key, keyMapper, units, jobClassName, options, args)
+ () -> doExecuteColocatedAsync(tableName, key, keyMapper, units, jobClassName, options, marshaler, args)
))
.thenCompose(Function.identity());
}
/** {@inheritDoc} */
@Override
- public <R> Map<ClusterNode, JobExecution<R>> submitBroadcast(
+ public <T, R> Map<ClusterNode, JobExecution<R>> submitBroadcast(
Set<ClusterNode> nodes,
- JobDescriptor descriptor,
- Object... args
+ JobDescriptor<T, R> descriptor,
+ T args
) {
Objects.requireNonNull(nodes);
Objects.requireNonNull(descriptor);
@@ -189,9 +209,11 @@ public class ClientCompute implements IgniteCompute {
Map<ClusterNode, JobExecution<R>> map = new HashMap<>(nodes.size());
for (ClusterNode node : nodes) {
- JobExecution<R> execution = new ClientJobExecution<>(ch, executeOnAnyNodeAsync(
- Set.of(node), descriptor.units(), descriptor.jobClassName(), descriptor.options(), args
- ));
+ JobExecution<R> execution = new ClientJobExecution<>(
+ ch,
+ executeOnAnyNodeAsync(Set.of(node), descriptor.units(), descriptor.jobClassName(), descriptor.options(),
+ descriptor.argumentMarshaler(), args),
+ descriptor.resultMarshaller());
if (map.put(node, execution) != null) {
throw new IllegalStateException("Node can't be specified more than once: " + node);
}
@@ -201,25 +223,26 @@ public class ClientCompute implements IgniteCompute {
}
@Override
- public <R> TaskExecution<R> submitMapReduce(List<DeploymentUnit> units, String taskClassName, Object... args) {
+ public <T, R> TaskExecution<R> submitMapReduce(List<DeploymentUnit> units, String taskClassName, T args) {
Objects.requireNonNull(units);
Objects.requireNonNull(taskClassName);
- return new ClientTaskExecution<>(ch, doExecuteMapReduceAsync(units, taskClassName, args));
+ return new ClientTaskExecution<>(ch, doExecuteMapReduceAsync(units, taskClassName, args, null));
}
@Override
- public <R> R executeMapReduce(List<DeploymentUnit> units, String taskClassName, Object... args) {
+ public <T, R> R executeMapReduce(List<DeploymentUnit> units, String taskClassName, T args) {
return sync(executeMapReduceAsync(units, taskClassName, args));
}
- private CompletableFuture<SubmitTaskResult> doExecuteMapReduceAsync(
+ private <T> CompletableFuture<SubmitTaskResult> doExecuteMapReduceAsync(
List<DeploymentUnit> units,
String taskClassName,
- Object... args) {
+ T args,
+ @Nullable Marshaler<Object, byte[]> marshaller) {
return ch.serviceAsync(
ClientOp.COMPUTE_EXECUTE_MAPREDUCE,
- w -> packTask(w.out(), units, taskClassName, args),
+ w -> packTask(w.out(), units, taskClassName, args, marshaller),
ClientCompute::unpackSubmitTaskResult,
null,
null,
@@ -227,12 +250,13 @@ public class ClientCompute implements IgniteCompute {
);
}
- private CompletableFuture<SubmitResult> executeOnAnyNodeAsync(
+ private <T> CompletableFuture<SubmitResult> executeOnAnyNodeAsync(
Set<ClusterNode> nodes,
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object[] args
+ @Nullable Marshaler<T, byte[]> marshaller,
+ T args
) {
ClusterNode node = randomNode(nodes);
@@ -240,7 +264,7 @@ public class ClientCompute implements IgniteCompute {
ClientOp.COMPUTE_EXECUTE,
w -> {
packNodeNames(w.out(), nodes);
- packJob(w.out(), units, jobClassName, options, args);
+ packJob(w.out(), units, jobClassName, options, marshaller, args);
},
ClientCompute::unpackSubmitResult,
node.name(),
@@ -264,14 +288,15 @@ public class ClientCompute implements IgniteCompute {
return iterator.next();
}
- private static <K> CompletableFuture<SubmitResult> executeColocatedObjectKey(
+ private static <K, T> CompletableFuture<SubmitResult> executeColocatedObjectKey(
ClientTable t,
K key,
Mapper<K> keyMapper,
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object[] args) {
+ @Nullable Marshaler<T, byte[]> marshaller,
+ T args) {
return executeColocatedInternal(
t,
(outputChannel, schema) -> ClientRecordSerializer.writeRecRaw(key, keyMapper, schema, outputChannel.out(), TuplePart.KEY),
@@ -279,16 +304,18 @@ public class ClientCompute implements IgniteCompute {
units,
jobClassName,
options,
+ marshaller,
args);
}
- private static CompletableFuture<SubmitResult> executeColocatedTupleKey(
+ private static <T> CompletableFuture<SubmitResult> executeColocatedTupleKey(
ClientTable t,
Tuple key,
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object[] args) {
+ @Nullable Marshaler<T, byte[]> marshaller,
+ T args) {
return executeColocatedInternal(
t,
(outputChannel, schema) -> ClientTupleSerializer.writeTupleRaw(key, schema, outputChannel, true),
@@ -296,17 +323,19 @@ public class ClientCompute implements IgniteCompute {
units,
jobClassName,
options,
+ marshaller,
args);
}
- private static CompletableFuture<SubmitResult> executeColocatedInternal(
+ private static <T> CompletableFuture<SubmitResult> executeColocatedInternal(
ClientTable t,
BiConsumer<PayloadOutputChannel, ClientSchema> keyWriter,
PartitionAwarenessProvider partitionAwarenessProvider,
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object[] args) {
+ @Nullable Marshaler<T, byte[]> marshaller,
+ T args) {
return t.doSchemaOutOpAsync(
ClientOp.COMPUTE_EXECUTE_COLOCATED,
(schema, outputChannel) -> {
@@ -317,7 +346,7 @@ public class ClientCompute implements IgniteCompute {
keyWriter.accept(outputChannel, schema);
- packJob(w, units, jobClassName, options, args);
+ packJob(w, units, jobClassName, options, marshaller, args);
},
ClientCompute::unpackSubmitResult,
partitionAwarenessProvider,
@@ -380,26 +409,29 @@ public class ClientCompute implements IgniteCompute {
}
}
- private static void packJob(ClientMessagePacker w,
+ private static <T> void packJob(ClientMessagePacker w,
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object[] args) {
+ @Nullable Marshaler<T, byte[]> marshaller,
+ T args
+ ) {
w.packDeploymentUnits(units);
w.packString(jobClassName);
w.packInt(options.priority());
w.packInt(options.maxRetries());
- w.packObjectArrayAsBinaryTuple(args);
+ w.packObjectAsBinaryTuple(args, marshaller);
}
private static void packTask(ClientMessagePacker w,
List<DeploymentUnit> units,
String taskClassName,
- Object[] args) {
+ Object args,
+ @Nullable Marshaler<Object, byte[]> marshaller) {
w.packDeploymentUnits(units);
w.packString(taskClassName);
- w.packObjectArrayAsBinaryTuple(args);
+ w.packObjectAsBinaryTuple(args, marshaller);
}
/**
@@ -415,9 +447,9 @@ public class ClientCompute implements IgniteCompute {
}
/**
- * Unpacks coordination job id and jobs ids which are executing under this task from channel and gets notification future.
- * This is needed because we need to unpack message response in the payload
- * reader because the unpacker will be closed after the response is processed.
+ * Unpacks coordination job id and jobs ids which are executing under this task from channel and gets notification future. This is
+ * needed because we need to unpack message response in the payload reader because the unpacker will be closed after the response is
+ * processed.
*
* @param ch Payload channel.
* @return Result of the task submission.
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientJobExecution.java b/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientJobExecution.java
index 8b277294e9..b08321a7ea 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientJobExecution.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientJobExecution.java
@@ -34,6 +34,7 @@ import org.apache.ignite.internal.client.proto.ClientOp;
import org.apache.ignite.internal.compute.JobStateImpl;
import org.apache.ignite.internal.compute.TaskStateImpl;
import org.apache.ignite.lang.IgniteException;
+import org.apache.ignite.marshaling.Marshaler;
import org.jetbrains.annotations.Nullable;
@@ -54,7 +55,7 @@ class ClientJobExecution<R> implements JobExecution<R> {
// Local state cache
private final CompletableFuture<@Nullable JobState> stateFuture = new CompletableFuture<>();
- ClientJobExecution(ReliableChannel ch, CompletableFuture<SubmitResult> reqFuture) {
+ ClientJobExecution(ReliableChannel ch, CompletableFuture<SubmitResult> reqFuture, @Nullable Marshaler<R, byte[]> marshaler) {
this.ch = ch;
jobIdFuture = reqFuture.thenApply(SubmitResult::jobId);
@@ -64,7 +65,9 @@ class ClientJobExecution<R> implements JobExecution<R> {
.thenApply(r -> {
// Notifications require explicit input close.
try (r) {
- R result = (R) r.in().unpackObjectFromBinaryTuple();
+ Object o = r.in().unpackObjectFromBinaryTuple();
+ R result = marshaler != null ? marshaler.unmarshal((byte[]) o) : (R) o;
+
stateFuture.complete(unpackJobState(r));
return result;
}
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientSql.java b/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientSql.java
index 437b945c4d..b1c1144b26 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientSql.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientSql.java
@@ -232,7 +232,7 @@ public class ClientSql implements IgniteSql {
w.out().packString(statement.query());
- w.out().packObjectArrayAsBinaryTuple(arguments);
+ w.out().packObjectArrayAsBinaryTuple(arguments, null);
w.out().packLong(ch.observableTimestamp());
};
@@ -309,7 +309,7 @@ public class ClientSql implements IgniteSql {
packProperties(w, null);
w.out().packString(query);
- w.out().packObjectArrayAsBinaryTuple(arguments);
+ w.out().packObjectArrayAsBinaryTuple(arguments, null);
w.out().packLong(ch.observableTimestamp());
};
@@ -331,7 +331,7 @@ public class ClientSql implements IgniteSql {
if (statementProps != null) {
for (Entry<String, Object> entry : statementProps.entrySet()) {
builder.appendString(entry.getKey());
- ClientBinaryTupleUtils.appendObject(builder, entry.getValue());
+ ClientBinaryTupleUtils.appendObject(builder, entry.getValue(), null);
}
}
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientDataStreamer.java b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientDataStreamer.java
index c07aae89fb..491d0122b0 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientDataStreamer.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientDataStreamer.java
@@ -33,6 +33,7 @@ import org.apache.ignite.internal.streamer.StreamerBatchSender;
import org.apache.ignite.internal.streamer.StreamerOptions;
import org.apache.ignite.internal.streamer.StreamerPartitionAwarenessProvider;
import org.apache.ignite.internal.streamer.StreamerSubscriber;
+import org.apache.ignite.marshaling.Marshaler;
import org.apache.ignite.table.DataStreamerItem;
import org.apache.ignite.table.DataStreamerOperationType;
import org.apache.ignite.table.DataStreamerOptions;
@@ -60,9 +61,9 @@ class ClientDataStreamer {
tbl);
}
- // T = key, E = element, V = payload, R = result.
+ // T = key, E = element, V = payload, R = result, A = Argument.
@SuppressWarnings("resource")
- static <T, E, V, R> CompletableFuture<Void> streamData(
+ static <T, E, V, R, A> CompletableFuture<Void> streamData(
Publisher<E> publisher,
Function<E, T> keyFunc,
Function<E, V> payloadFunc,
@@ -73,7 +74,9 @@ class ClientDataStreamer {
@Nullable Flow.Subscriber<R> resultSubscriber,
List<DeploymentUnit> deploymentUnits,
String receiverClassName,
- Object... receiverArgs) {
+ A receiverArgs,
+ @Nullable Marshaler<A, byte[]> receiverArgsMarshaller
+ ) {
StreamerBatchSender<V, Integer, R> batchSender = (partitionId, items, deleted) ->
tbl.getPartitionAssignment().thenCompose(
partitionAssignment -> tbl.channel().serviceAsync(
@@ -87,7 +90,7 @@ class ClientDataStreamer {
w.packDeploymentUnits(deploymentUnits);
w.packBoolean(resultSubscriber != null); // receiveResults
- StreamerReceiverSerializer.serialize(w, receiverClassName, receiverArgs, items);
+ StreamerReceiverSerializer.serialize(w, receiverClassName, receiverArgs, receiverArgsMarshaller, items);
},
in -> resultSubscriber != null
? StreamerReceiverSerializer.deserializeResults(in.in())
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueBinaryView.java b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueBinaryView.java
index ffac72f177..cf83698a5e 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueBinaryView.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueBinaryView.java
@@ -488,14 +488,14 @@ public class ClientKeyValueBinaryView extends AbstractClientView<Entry<Tuple, Tu
/** {@inheritDoc} */
@Override
- public <E, V, R> CompletableFuture<Void> streamData(
+ public <E, V, R, A> CompletableFuture<Void> streamData(
Publisher<E> publisher,
Function<E, Entry<Tuple, Tuple>> keyFunc,
Function<E, V> payloadFunc,
- ReceiverDescriptor receiver,
+ ReceiverDescriptor<A> receiver,
@Nullable Flow.Subscriber<R> resultSubscriber,
@Nullable DataStreamerOptions options,
- Object... receiverArgs) {
+ A receiverArg) {
Objects.requireNonNull(publisher);
Objects.requireNonNull(keyFunc);
Objects.requireNonNull(payloadFunc);
@@ -512,7 +512,9 @@ public class ClientKeyValueBinaryView extends AbstractClientView<Entry<Tuple, Tu
resultSubscriber,
receiver.units(),
receiver.receiverClassName(),
- receiverArgs);
+ receiverArg,
+ receiver.argumentsMarshaler()
+ );
}
/** {@inheritDoc} */
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueView.java b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueView.java
index a0181a6e22..fc82797b57 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueView.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueView.java
@@ -684,14 +684,14 @@ public class ClientKeyValueView<K, V> extends AbstractClientView<Entry<K, V>> im
/** {@inheritDoc} */
@Override
- public <E, P, R> CompletableFuture<Void> streamData(
+ public <E, P, R, A> CompletableFuture<Void> streamData(
Publisher<E> publisher,
Function<E, Entry<K, V>> keyFunc,
Function<E, P> payloadFunc,
- ReceiverDescriptor receiver,
+ ReceiverDescriptor<A> receiver,
@Nullable Flow.Subscriber<R> resultSubscriber,
@Nullable DataStreamerOptions options,
- Object... receiverArgs) {
+ A receiverArg) {
Objects.requireNonNull(publisher);
Objects.requireNonNull(keyFunc);
Objects.requireNonNull(payloadFunc);
@@ -708,7 +708,9 @@ public class ClientKeyValueView<K, V> extends AbstractClientView<Entry<K, V>> im
resultSubscriber,
receiver.units(),
receiver.receiverClassName(),
- receiverArgs);
+ receiverArg,
+ receiver.argumentsMarshaler()
+ );
}
/** {@inheritDoc} */
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordBinaryView.java b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordBinaryView.java
index 13dd19f024..4c91b7ffeb 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordBinaryView.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordBinaryView.java
@@ -419,14 +419,14 @@ public class ClientRecordBinaryView extends AbstractClientView<Tuple> implements
/** {@inheritDoc} */
@Override
- public <E, V, R> CompletableFuture<Void> streamData(
+ public <E, V, R, A> CompletableFuture<Void> streamData(
Publisher<E> publisher,
Function<E, Tuple> keyFunc,
Function<E, V> payloadFunc,
- ReceiverDescriptor receiver,
+ ReceiverDescriptor<A> receiver,
@Nullable Flow.Subscriber<R> resultSubscriber,
@Nullable DataStreamerOptions options,
- Object... receiverArgs) {
+ A receiverArg) {
Objects.requireNonNull(publisher);
Objects.requireNonNull(keyFunc);
Objects.requireNonNull(payloadFunc);
@@ -443,6 +443,8 @@ public class ClientRecordBinaryView extends AbstractClientView<Tuple> implements
resultSubscriber,
receiver.units(),
receiver.receiverClassName(),
- receiverArgs);
+ receiverArg,
+ receiver.argumentsMarshaler()
+ );
}
}
diff --git a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordView.java b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordView.java
index b8acd7e734..7b58792401 100644
--- a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordView.java
+++ b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordView.java
@@ -421,14 +421,14 @@ public class ClientRecordView<R> extends AbstractClientView<R> implements Record
}
@Override
- public <E, V, R1> CompletableFuture<Void> streamData(
+ public <E, V, R1, A> CompletableFuture<Void> streamData(
Publisher<E> publisher,
Function<E, R> keyFunc,
Function<E, V> payloadFunc,
- ReceiverDescriptor receiver,
+ ReceiverDescriptor<A> receiver,
@Nullable Flow.Subscriber<R1> resultSubscriber,
@Nullable DataStreamerOptions options,
- Object... receiverArgs) {
+ A receiverArg) {
Objects.requireNonNull(publisher);
Objects.requireNonNull(keyFunc);
Objects.requireNonNull(payloadFunc);
@@ -445,7 +445,9 @@ public class ClientRecordView<R> extends AbstractClientView<R> implements Record
resultSubscriber,
receiver.units(),
receiver.receiverClassName(),
- receiverArgs);
+ receiverArg,
+ receiver.argumentsMarshaler()
+ );
}
/** {@inheritDoc} */
diff --git a/modules/client/src/test/java/org/apache/ignite/client/ClientComputeTest.java b/modules/client/src/test/java/org/apache/ignite/client/ClientComputeTest.java
index f450823243..c371559098 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/ClientComputeTest.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/ClientComputeTest.java
@@ -95,9 +95,9 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
JobDescriptor job = JobDescriptor.builder("job").build();
- JobExecution<String> execution1 = client.compute().submit(getClusterNodes("s1"), job);
- JobExecution<String> execution2 = client.compute().submit(getClusterNodes("s2"), job);
- JobExecution<String> execution3 = client.compute().submit(getClusterNodes("s3"), job);
+ JobExecution<String> execution1 = client.compute().submit(getClusterNodes("s1"), job, null);
+ JobExecution<String> execution2 = client.compute().submit(getClusterNodes("s2"), job, null);
+ JobExecution<String> execution3 = client.compute().submit(getClusterNodes("s3"), job, null);
assertThat(execution1.resultAsync(), willBe("s1"));
assertThat(execution2.resultAsync(), willBe("s2"));
@@ -116,9 +116,9 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
try (var client = getClient(server3)) {
JobDescriptor job = JobDescriptor.builder("job").build();
- JobExecution<String> execution1 = client.compute().submit(getClusterNodes("s1"), job);
- JobExecution<String> execution2 = client.compute().submit(getClusterNodes("s2"), job);
- JobExecution<String> execution3 = client.compute().submit(getClusterNodes("s3"), job);
+ JobExecution<String> execution1 = client.compute().submit(getClusterNodes("s1"), job, null);
+ JobExecution<String> execution2 = client.compute().submit(getClusterNodes("s2"), job, null);
+ JobExecution<String> execution3 = client.compute().submit(getClusterNodes("s3"), job, null);
assertThat(execution1.resultAsync(), willBe("s3"));
assertThat(execution2.resultAsync(), willBe("s3"));
@@ -140,7 +140,7 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
var nodeName = "s" + nodeId;
JobDescriptor job = JobDescriptor.builder("job").build();
- CompletableFuture<String> fut = client.compute().executeAsync(getClusterNodes(nodeName), job);
+ CompletableFuture<String> fut = client.compute().executeAsync(getClusterNodes(nodeName), job, null);
assertThat(fut, willBe("s3"));
}
@@ -152,10 +152,10 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
initServers(reqId -> false);
try (var client = getClient(server2)) {
- JobDescriptor job = JobDescriptor.builder("job").build();
+ JobDescriptor<Object, String> job = JobDescriptor.<Object, String>builder("job").build();
- String res1 = client.compute().execute(JobTarget.colocated(TABLE_NAME, Tuple.create().set("key", "k")), job);
- String res2 = client.compute().execute(JobTarget.colocated(TABLE_NAME, 1L, Mapper.of(Long.class)), job);
+ String res1 = client.compute().execute(JobTarget.colocated(TABLE_NAME, Tuple.create().set("key", "k")), job, null);
+ String res2 = client.compute().execute(JobTarget.colocated(TABLE_NAME, 1L, Mapper.of(Long.class)), job, null);
assertEquals("s2", res1);
assertEquals("s2", res2);
@@ -169,8 +169,19 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
try (var client = getClient(server2)) {
JobDescriptor job = JobDescriptor.builder("job").build();
- JobExecution<String> execution1 = client.compute().submit(JobTarget.colocated(TABLE_NAME, Tuple.create().set("key", "k")), job);
- JobExecution<String> execution2 = client.compute().submit(JobTarget.colocated(TABLE_NAME, 1L, Mapper.of(Long.class)), job);
+ JobExecution<String> execution1 = client.compute().submit(JobTarget.colocated(
+ TABLE_NAME,
+ Tuple.create().set("key", "k")),
+ job,
+ null
+ );
+ JobExecution<String> execution2 = client.compute().submit(JobTarget.colocated(
+ TABLE_NAME,
+ 1L,
+ Mapper.of(Long.class)),
+ job,
+ null
+ );
assertThat(execution1.resultAsync(), willBe("s2"));
assertThat(execution2.resultAsync(), willBe("s2"));
@@ -189,7 +200,7 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
var ex = assertThrows(CompletionException.class,
() -> client.compute().executeAsync(
- JobTarget.colocated("bad-tbl", key), JobDescriptor.builder("job").build()).join());
+ JobTarget.colocated("bad-tbl", key), JobDescriptor.builder("job").build(), null).join());
var tblNotFoundEx = (TableNotFoundException) ex.getCause();
assertThat(tblNotFoundEx.getMessage(), containsString("The table does not exist [name=\"PUBLIC\".\"bad-tbl\"]"));
@@ -208,7 +219,9 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
try (var client = getClient(server3)) {
Tuple key = Tuple.create().set("key", "k");
- String res1 = client.compute().execute(JobTarget.colocated(tableName, key), JobDescriptor.builder("job").build());
+ String res1 = client.compute().execute(
+ JobTarget.colocated(tableName, key), JobDescriptor.<Object, String>builder("job").build(), null
+ );
// Drop table and create a new one with a different ID.
((FakeIgniteTables) ignite.tables()).dropTable(tableName);
@@ -222,8 +235,13 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
}
String res2 = client.compute().execute(
- JobTarget.colocated(tableName, 1L, Mapper.of(Long.class)),
- JobDescriptor.builder("job").build());
+ JobTarget.colocated(
+ tableName,
+ 1L,
+ Mapper.of(Long.class)),
+ JobDescriptor.<Object, String>builder("job").build(),
+ null
+ );
assertEquals("s3", res1);
assertEquals("s3", res2);
@@ -235,7 +253,7 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
initServers(reqId -> false);
try (var client = getClient(server1)) {
- Object[] args = {"arg1", 2};
+ Object args = "arg1";
String res1 = client.compute().executeMapReduce(List.of(), "job", args);
assertEquals("s1", res1);
}
@@ -246,7 +264,7 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
initServers(reqId -> false);
try (var client = getClient(server1)) {
- TaskExecution<Object> task = client.compute().submitMapReduce(List.of(), "job");
+ TaskExecution<Object> task = client.compute().submitMapReduce(List.of(), "job", null);
assertThat(task.resultAsync(), willBe("s1"));
@@ -265,7 +283,7 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
try (var client = getClient(server1)) {
FakeCompute.future = CompletableFuture.failedFuture(new RuntimeException("job failed"));
- TaskExecution<Object> execution = client.compute().submitMapReduce(List.of(), "job");
+ TaskExecution<Object> execution = client.compute().submitMapReduce(List.of(), "job", null);
assertThat(execution.resultAsync(), willThrowFast(IgniteException.class));
assertThat(execution.stateAsync(), willBe(taskStateWithStatus(TaskStatus.FAILED)));
@@ -289,7 +307,8 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
}
private static String getUnits(IgniteClient client, List<DeploymentUnit> units) {
- return client.compute().execute(getClusterNodes("s1"), JobDescriptor.builder(FakeCompute.GET_UNITS).units(units).build());
+ return client.compute().execute(getClusterNodes("s1"),
+ JobDescriptor.<Object, String>builder(FakeCompute.GET_UNITS).units(units).build(), null);
}
@Test
@@ -301,7 +320,7 @@ public class ClientComputeTest extends BaseIgniteAbstractTest {
IgniteCompute igniteCompute = client.compute();
var jobTarget = getClusterNodes("s1");
- JobExecution<String> execution = igniteCompute.submit(jobTarget, JobDescriptor.builder("job").build());
+ JobExecution<String> execution = igniteCompute.submit(jobTarget, JobDescriptor.<Object, String>builder("job").build(), null);
assertThat(execution.resultAsync(), willThrowFast(IgniteException.class));
assertThat(execution.stateAsync(), willBe(jobStateWithStatus(FAILED)));
diff --git a/modules/client/src/test/java/org/apache/ignite/client/DataStreamerTest.java b/modules/client/src/test/java/org/apache/ignite/client/DataStreamerTest.java
index 178901abc4..906f0c6662 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/DataStreamerTest.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/DataStreamerTest.java
@@ -252,8 +252,9 @@ public class DataStreamerTest extends AbstractClientTableTest {
DataStreamerItem::get,
t -> t.get().longValue("id"),
ReceiverDescriptor.builder(TestUpsertReceiver.class).build(),
- null,
- options)
+ null,
+ options,
+ null)
: view.streamData(publisher, options);
for (long i = 0; i < 1000; i++) {
@@ -373,7 +374,7 @@ public class DataStreamerTest extends AbstractClientTableTest {
ReceiverDescriptor.builder(TestReceiver.class).build(),
null,
options,
- "arg");
+ ":arg:");
for (long i = 0; i < count; i++) {
publisher.submit(tuple(i));
@@ -405,8 +406,7 @@ public class DataStreamerTest extends AbstractClientTableTest {
ReceiverDescriptor.builder(TestReceiver.class).build(),
resultSubscriber,
options,
- "arg",
- "returnResults");
+ "returnResults:arg");
for (long i = 0; i < count; i++) {
publisher.submit(tuple(i));
@@ -444,8 +444,7 @@ public class DataStreamerTest extends AbstractClientTableTest {
ReceiverDescriptor.builder(TestReceiver.class).build(),
resultSubscriber,
null,
- "arg",
- withSubscriber ? "returnResults" : "noResults");
+ (withSubscriber ? "returnResults" : "noResults") + ":arg");
for (long i = 0; i < count; i++) {
publisher.submit(new PersonPojo(i));
@@ -486,8 +485,8 @@ public class DataStreamerTest extends AbstractClientTableTest {
ReceiverDescriptor.builder(TestReceiver.class).build(),
resultSubscriber,
null,
- "arg",
- withSubscriber ? "returnResults" : "noResults");
+ (withSubscriber ? "returnResults" : "noResults") + ":arg"
+ );
for (long i = 0; i < count; i++) {
publisher.submit(Map.entry(tupleKey(i), tupleVal("foo")));
@@ -528,8 +527,8 @@ public class DataStreamerTest extends AbstractClientTableTest {
ReceiverDescriptor.builder(TestReceiver.class).build(),
resultSubscriber,
null,
- "arg",
- withSubscriber ? "returnResults" : "noResults");
+ (withSubscriber ? "returnResults" : "noResults") + ":arg"
+ );
for (long i = 0; i < count; i++) {
publisher.submit(Map.entry(i, new PersonValPojo("foo")));
@@ -593,9 +592,8 @@ public class DataStreamerTest extends AbstractClientTableTest {
ReceiverDescriptor.builder(TestReceiver.class).build(),
resultSubscriber,
options,
- "arg",
- resultCount < 0 ? null : "returnResults",
- resultCount);
+ (resultCount < 0 ? null : "returnResults") + ":arg:" + resultCount
+ );
for (long i = 0; i < 3; i++) {
publisher.submit(tuple(i));
@@ -624,8 +622,8 @@ public class DataStreamerTest extends AbstractClientTableTest {
ReceiverDescriptor.builder(TestReceiver.class).build(),
resultSubscriber,
options,
- "arg",
- "returnResults");
+ "returnResults:arg"
+ );
for (long i = 0; i < 3; i++) {
publisher.submit(tuple(i));
@@ -651,8 +649,8 @@ public class DataStreamerTest extends AbstractClientTableTest {
ReceiverDescriptor.builder(TestReceiver.class).build(),
null,
options,
- "arg",
- "returnResults");
+ "arg:returnResults"
+ );
for (long i = 0; i < 3; i++) {
publisher.submit(tuple(i));
@@ -729,18 +727,19 @@ public class DataStreamerTest extends AbstractClientTableTest {
return ignite2;
}
- private static class TestReceiver implements DataStreamerReceiver<Long, String> {
+ private static class TestReceiver implements DataStreamerReceiver<Long, Object, String> {
@Override
- public CompletableFuture<List<String>> receive(List<Long> page, DataStreamerReceiverContext ctx, Object... args) {
- boolean returnResults = args.length > 1 && "returnResults".equals(args[1]);
- int resultCount = args.length > 2 ? (int) args[2] : page.size();
+ public CompletableFuture<List<String>> receive(List<Long> page, DataStreamerReceiverContext ctx, Object arg) {
+ var parsedArgs = TestReceiverArs.from(arg);
// noinspection resource
RecordView<Tuple> view = ctx.ignite().tables().table(DEFAULT_TABLE).recordView();
List<String> res = new ArrayList<>(page.size());
+ int resultCount = parsedArgs.resultCount < 0 ? page.size() : parsedArgs.resultCount;
+
for (Long id : page) {
- String name = "recv_" + args[0] + "_" + id;
+ String name = "recv_" + parsedArgs.arg + "_" + id;
view.upsert(null, tuple(id, name));
if (resultCount-- > 0) {
@@ -752,14 +751,40 @@ public class DataStreamerTest extends AbstractClientTableTest {
res.add("extra_" + resultCount);
}
- return CompletableFuture.completedFuture(returnResults ? res : null);
+ return CompletableFuture.completedFuture(parsedArgs.returnResults ? res : null);
+ }
+
+ static class TestReceiverArs {
+ final boolean returnResults;
+ final String arg;
+ final int resultCount;
+
+ TestReceiverArs(boolean returnResults, String arg, int resultCount) {
+ this.returnResults = returnResults;
+ this.arg = arg;
+ this.resultCount = resultCount;
+ }
+
+ static TestReceiverArs from(@Nullable Object str) {
+ if (str == null) {
+ return new TestReceiverArs(false, null, -1);
+ }
+
+ String[] split = ((String) str).split(":");
+ boolean returnResults = "returnResults".equals(split[0]);
+ String arg = split[1];
+ int resultCount = split.length > 2 ? Integer.parseInt(split[2]) : -1;
+
+ return new TestReceiverArs(returnResults, arg, resultCount);
+ }
+
}
}
- private static class TestUpsertReceiver implements DataStreamerReceiver<Long, Void> {
+ private static class TestUpsertReceiver implements DataStreamerReceiver<Long, Object, Void> {
@Override
@Nullable
- public CompletableFuture<List<Void>> receive(List<Long> page, DataStreamerReceiverContext ctx, Object... args) {
+ public CompletableFuture<List<Void>> receive(List<Long> page, DataStreamerReceiverContext ctx, Object arg) {
// noinspection resource
RecordView<Tuple> view = ctx.ignite().tables().table(DEFAULT_TABLE).recordView();
@@ -810,10 +835,10 @@ public class DataStreamerTest extends AbstractClientTableTest {
}
}
- private static class EchoArgsReceiver implements DataStreamerReceiver<Object, Object> {
+ private static class EchoArgsReceiver implements DataStreamerReceiver<Object, Object, Object> {
@Override
- public CompletableFuture<List<Object>> receive(List<Object> page, DataStreamerReceiverContext ctx, Object... args) {
- return CompletableFuture.completedFuture(List.of(args));
+ public CompletableFuture<List<Object>> receive(List<Object> page, DataStreamerReceiverContext ctx, Object arg) {
+ return CompletableFuture.completedFuture(List.of(arg));
}
}
}
diff --git a/modules/client/src/test/java/org/apache/ignite/client/PartitionAwarenessTest.java b/modules/client/src/test/java/org/apache/ignite/client/PartitionAwarenessTest.java
index 43e8d9ee96..633a1eb717 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/PartitionAwarenessTest.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/PartitionAwarenessTest.java
@@ -446,20 +446,20 @@ public class PartitionAwarenessTest extends AbstractClientTest {
Tuple t1 = Tuple.create().set("ID", 1L);
Tuple t2 = Tuple.create().set("ID", 2L);
- JobDescriptor job = JobDescriptor.builder("job").build();
+ JobDescriptor<Object, String> job = JobDescriptor.<Object, String>builder("job").build();
- assertThat(compute().executeAsync(JobTarget.colocated(table.name(), t1), job), willBe(nodeKey1));
- assertThat(compute().executeAsync(JobTarget.colocated(table.name(), t2), job), willBe(nodeKey2));
+ assertThat(compute().executeAsync(JobTarget.colocated(table.name(), t1), job, null), willBe(nodeKey1));
+ assertThat(compute().executeAsync(JobTarget.colocated(table.name(), t2), job, null), willBe(nodeKey2));
}
@Test
public void testExecuteColocatedObjectKeyRoutesRequestToPrimaryNode() {
var mapper = Mapper.of(Long.class);
Table table = defaultTable();
- JobDescriptor job = JobDescriptor.builder("job").build();
+ JobDescriptor<Object, String> job = JobDescriptor.<Object, String>builder("job").build();
- assertThat(compute().executeAsync(JobTarget.colocated(table.name(), 1L, mapper), job), willBe(nodeKey1));
- assertThat(compute().executeAsync(JobTarget.colocated(table.name(), 2L, mapper), job), willBe(nodeKey2));
+ assertThat(compute().executeAsync(JobTarget.colocated(table.name(), 1L, mapper), job, null), willBe(nodeKey1));
+ assertThat(compute().executeAsync(JobTarget.colocated(table.name(), 2L, mapper), job, null), willBe(nodeKey2));
}
@ParameterizedTest
@@ -472,7 +472,7 @@ public class PartitionAwarenessTest extends AbstractClientTest {
try (SimplePublisher<Tuple> publisher = new SimplePublisher<>()) {
fut = withReceiver
- ? recordView.streamData(publisher, DataStreamerItem::get, x -> 0, receiver(), null, null)
+ ? recordView.streamData(publisher, DataStreamerItem::get, x -> 0, receiver(), null, null, null)
: recordView.streamData(publisher, null);
publisher.submit(t);
@@ -498,7 +498,7 @@ public class PartitionAwarenessTest extends AbstractClientTest {
try (SimplePublisher<PersonPojo> publisher = new SimplePublisher<>()) {
fut = withReceiver
- ? pojoView.streamData(publisher, DataStreamerItem::get, x -> 0, receiver(), null, null)
+ ? pojoView.streamData(publisher, DataStreamerItem::get, x -> 0, receiver(), null, null, null)
: pojoView.streamData(publisher, null);
publisher.submit(t);
@@ -524,7 +524,7 @@ public class PartitionAwarenessTest extends AbstractClientTest {
try (SimplePublisher<Entry<Tuple, Tuple>> publisher = new SimplePublisher<>()) {
fut = withReceiver
- ? recordView.streamData(publisher, DataStreamerItem::get, x -> 0, receiver(), null, null)
+ ? recordView.streamData(publisher, DataStreamerItem::get, x -> 0, receiver(), null, null, null)
: recordView.streamData(publisher, null);
publisher.submit(Map.entry(t, Tuple.create()));
}
@@ -540,7 +540,7 @@ public class PartitionAwarenessTest extends AbstractClientTest {
}
@ParameterizedTest
- @ValueSource(booleans = {true, false})
+ @ValueSource(booleans = {true})
public void testDataStreamerKeyValueView(boolean withReceiver) {
KeyValueView<Long, String> kvView = defaultTable().keyValueView(Mapper.of(Long.class), Mapper.of(String.class));
@@ -549,7 +549,7 @@ public class PartitionAwarenessTest extends AbstractClientTest {
try (SimplePublisher<Entry<Long, String>> publisher = new SimplePublisher<>()) {
fut = withReceiver
- ? kvView.streamData(publisher, DataStreamerItem::get, x -> 0, receiver(), null, null)
+ ? kvView.streamData(publisher, DataStreamerItem::get, x -> 0, receiver(), null, null, null)
: kvView.streamData(publisher, null);
publisher.submit(Map.entry(t, t.toString()));
}
@@ -685,14 +685,14 @@ public class PartitionAwarenessTest extends AbstractClientTest {
return List.of(testServer2.nodeName(), testServer.nodeName(), testServer2.nodeName(), testServer.nodeName());
}
- private static ReceiverDescriptor receiver() {
- return ReceiverDescriptor.builder(TestReceiver.class).build();
+ private static <A> ReceiverDescriptor<A> receiver() {
+ return (ReceiverDescriptor<A>) ReceiverDescriptor.builder(TestReceiver.class).build();
}
- private static class TestReceiver implements DataStreamerReceiver<Object, Object> {
+ private static class TestReceiver implements DataStreamerReceiver<Object, Object, Object> {
@SuppressWarnings("resource")
@Override
- public CompletableFuture<List<Object>> receive(List<Object> page, DataStreamerReceiverContext ctx, Object... args) {
+ public CompletableFuture<List<Object>> receive(List<Object> page, DataStreamerReceiverContext ctx, Object arg) {
ctx.ignite().tables().table(DEFAULT_TABLE).recordView().upsert(null, Tuple.create().set("ID", 0L));
return CompletableFuture.completedFuture(null);
}
diff --git a/modules/client/src/test/java/org/apache/ignite/client/RequestBalancingTest.java b/modules/client/src/test/java/org/apache/ignite/client/RequestBalancingTest.java
index 0e595b1013..f4ef7e150b 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/RequestBalancingTest.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/RequestBalancingTest.java
@@ -67,7 +67,7 @@ public class RequestBalancingTest extends BaseIgniteAbstractTest {
// Execute on unknown node to fall back to balancing.
List<Object> res = IntStream.range(0, 5)
- .mapToObj(i -> client.compute().execute(getClusterNodes("s123"), JobDescriptor.builder("job").build()))
+ .mapToObj(i -> client.compute().execute(getClusterNodes("s123"), JobDescriptor.builder("job").build(), null))
.collect(Collectors.toList());
assertEquals(5, res.size());
diff --git a/modules/client/src/test/java/org/apache/ignite/client/ServerMetricsTest.java b/modules/client/src/test/java/org/apache/ignite/client/ServerMetricsTest.java
index aeca6c05a6..b57065032d 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/ServerMetricsTest.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/ServerMetricsTest.java
@@ -93,7 +93,7 @@ public class ServerMetricsTest extends AbstractClientTest {
FakeCompute.latch = new CountDownLatch(1);
- client.compute().submit(getClusterNodes("s1"), JobDescriptor.builder("job").build());
+ client.compute().submit(getClusterNodes("s1"), JobDescriptor.builder("job").build(), null);
assertTrue(
IgniteTestUtils.waitForCondition(() -> testServer.metrics().requestsActive() == 1, 1000),
@@ -110,7 +110,7 @@ public class ServerMetricsTest extends AbstractClientTest {
public void testRequestsProcessed() throws Exception {
long processed = testServer.metrics().requestsProcessed();
- client.compute().submit(getClusterNodes("s1"), JobDescriptor.builder("job").build());
+ client.compute().submit(getClusterNodes("s1"), JobDescriptor.builder("job").build(), null);
assertTrue(
IgniteTestUtils.waitForCondition(() -> testServer.metrics().requestsProcessed() == processed + 1, 1000),
@@ -123,7 +123,7 @@ public class ServerMetricsTest extends AbstractClientTest {
FakeCompute.err = new RuntimeException("test");
- client.compute().submit(getClusterNodes("s1"), JobDescriptor.builder("job").build());
+ client.compute().submit(getClusterNodes("s1"), JobDescriptor.builder("job").build(), null);
assertTrue(
IgniteTestUtils.waitForCondition(() -> testServer.metrics().requestsFailed() == 1, 1000),
@@ -137,7 +137,7 @@ public class ServerMetricsTest extends AbstractClientTest {
assertFalse(testServer.metrics().enabled());
assertEquals(0, testServer.metrics().requestsProcessed());
- client.compute().execute(getClusterNodes("s1"), JobDescriptor.builder("job").build());
+ client.compute().execute(getClusterNodes("s1"), JobDescriptor.builder("job").build(), null);
assertEquals(0, testServer.metrics().requestsProcessed());
assertFalse(testServer.metrics().enabled());
diff --git a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeCompute.java b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeCompute.java
index 9fe5fdb74e..0ee7a5db59 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeCompute.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeCompute.java
@@ -93,7 +93,7 @@ public class FakeCompute implements IgniteComputeInternal {
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object... args) {
+ Object args) {
if (Objects.equals(jobClassName, GET_UNITS)) {
String unitString = units.stream().map(DeploymentUnit::render).collect(Collectors.joining(","));
return completedExecution((R) unitString);
@@ -111,8 +111,8 @@ public class FakeCompute implements IgniteComputeInternal {
}
if (jobClassName.startsWith("org.apache.ignite")) {
- Class<ComputeJob<R>> jobClass = ComputeUtils.jobClass(this.getClass().getClassLoader(), jobClassName);
- ComputeJob<R> job = ComputeUtils.instantiateJob(jobClass);
+ Class<ComputeJob<Object, R>> jobClass = ComputeUtils.jobClass(this.getClass().getClassLoader(), jobClassName);
+ ComputeJob<Object, R> job = ComputeUtils.instantiateJob(jobClass);
CompletableFuture<R> jobFut = job.executeAsync(
new JobExecutionContextImpl(ignite, new AtomicBoolean(), this.getClass().getClassLoader()), args);
@@ -125,13 +125,14 @@ public class FakeCompute implements IgniteComputeInternal {
/** {@inheritDoc} */
@Override
- public <R> CompletableFuture<JobExecution<R>> submitColocatedInternal(TableViewInternal table, Tuple key, List<DeploymentUnit> units,
- String jobClassName, JobExecutionOptions options, Object[] args) {
+ public <R> CompletableFuture<JobExecution<R>> submitColocatedInternal(
+ TableViewInternal table, Tuple key, List<DeploymentUnit> units, String jobClassName,
+ JobExecutionOptions options, Object args) {
return completedFuture(jobExecution(future != null ? future : completedFuture((R) nodeName)));
}
@Override
- public <R> JobExecution<R> submit(JobTarget target, JobDescriptor descriptor, Object... args) {
+ public <T, R> JobExecution<R> submit(JobTarget target, JobDescriptor<T, R> descriptor, T args) {
if (target instanceof AnyNodeJobTarget) {
Set<ClusterNode> nodes = ((AnyNodeJobTarget) target).nodes();
return executeAsyncWithFailover(nodes, descriptor.units(), descriptor.jobClassName(), descriptor.options(), args);
@@ -143,26 +144,26 @@ public class FakeCompute implements IgniteComputeInternal {
}
@Override
- public <R> R execute(JobTarget target, JobDescriptor descriptor, Object... args) {
+ public <T, R> R execute(JobTarget target, JobDescriptor<T, R> descriptor, T args) {
return sync(executeAsync(target, descriptor, args));
}
@Override
- public <R> Map<ClusterNode, JobExecution<R>> submitBroadcast(
+ public <T, R> Map<ClusterNode, JobExecution<R>> submitBroadcast(
Set<ClusterNode> nodes,
- JobDescriptor descriptor,
- Object... args
+ JobDescriptor<T, R> descriptor,
+ T args
) {
return null;
}
@Override
- public <R> TaskExecution<R> submitMapReduce(List<DeploymentUnit> units, String taskClassName, Object... args) {
+ public <T, R> TaskExecution<R> submitMapReduce(List<DeploymentUnit> units, String taskClassName, T args) {
return taskExecution(future != null ? future : completedFuture((R) nodeName));
}
@Override
- public <R> R executeMapReduce(List<DeploymentUnit> units, String taskClassName, Object... args) {
+ public <T, R> R executeMapReduce(List<DeploymentUnit> units, String taskClassName, T args) {
return sync(executeMapReduceAsync(units, taskClassName, args));
}
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeBaseTest.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeBaseTest.java
index a78b529b3a..de8c3597b5 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeBaseTest.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeBaseTest.java
@@ -29,6 +29,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.aMapWithSize;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.in;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
@@ -44,6 +45,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
import org.apache.ignite.Ignite;
+import org.apache.ignite.client.IgniteClient;
import org.apache.ignite.compute.ComputeException;
import org.apache.ignite.compute.JobDescriptor;
import org.apache.ignite.compute.JobExecution;
@@ -55,6 +57,7 @@ import org.apache.ignite.internal.app.IgniteImpl;
import org.apache.ignite.internal.util.ExceptionUtils;
import org.apache.ignite.lang.IgniteException;
import org.apache.ignite.lang.TableNotFoundException;
+import org.apache.ignite.marshaling.ByteArrayMarshaler;
import org.apache.ignite.network.ClusterNode;
import org.apache.ignite.table.Tuple;
import org.apache.ignite.table.mapper.Mapper;
@@ -85,8 +88,13 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
void executesWrongJobClassLocally(String jobClassName, int errorCode, String msg) {
IgniteImpl entryNode = node(0);
- IgniteException ex = assertThrows(IgniteException.class, () ->
- entryNode.compute().execute(JobTarget.node(entryNode.node()), JobDescriptor.builder(jobClassName).units(units()).build()));
+ IgniteException ex = assertThrows(
+ IgniteException.class, () ->
+ entryNode.compute().execute(
+ JobTarget.node(entryNode.node()),
+ JobDescriptor.builder(jobClassName).units(units()).build(),
+ null
+ ));
assertTraceableException(ex, ComputeException.class, errorCode, msg);
}
@@ -97,7 +105,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
IgniteImpl entryNode = node(0);
ExecutionException ex = assertThrows(ExecutionException.class, () -> entryNode.compute().executeAsync(
- JobTarget.node(entryNode.node()), JobDescriptor.builder(jobClassName).units(units()).build())
+ JobTarget.node(entryNode.node()), JobDescriptor.builder(jobClassName).units(units()).build(), null)
.get(1, TimeUnit.SECONDS));
assertTraceableException(ex, ComputeException.class, errorCode, msg);
@@ -110,7 +118,8 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
IgniteException ex = assertThrows(IgniteException.class, () -> entryNode.compute().execute(
JobTarget.anyNode(node(1).node(), node(2).node()),
- JobDescriptor.builder(jobClassName).units(units()).build()));
+ JobDescriptor.builder(jobClassName).units(units()).build(),
+ null));
assertTraceableException(ex, ComputeException.class, errorCode, msg);
}
@@ -121,7 +130,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
Ignite entryNode = node(0);
ExecutionException ex = assertThrows(ExecutionException.class, () -> entryNode.compute().executeAsync(
- JobTarget.anyNode(node(1).node(), node(2).node()), JobDescriptor.builder(jobClassName).units(units()).build())
+ JobTarget.anyNode(node(1).node(), node(2).node()), JobDescriptor.builder(jobClassName).units(units()).build(), null)
.get(1, TimeUnit.SECONDS));
assertTraceableException(ex, ComputeException.class, errorCode, msg);
@@ -133,8 +142,8 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
String result = entryNode.compute().execute(
JobTarget.node(entryNode.node()),
- JobDescriptor.builder(concatJobClassName()).units(units()).build(),
- "a", 42);
+ JobDescriptor.builder(concatJobClass()).units(units()).build(),
+ new Object[]{"a", 42});
assertThat(result, is("a42"));
}
@@ -145,8 +154,8 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
JobExecution<String> execution = entryNode.compute().submit(
JobTarget.node(entryNode.node()),
- JobDescriptor.builder(concatJobClassName()).units(units()).build(),
- "a", 42);
+ JobDescriptor.builder(concatJobClass()).units(units()).build(),
+ new Object[] {"a", 42});
assertThat(execution.resultAsync(), willBe("a42"));
assertThat(execution.stateAsync(), willBe(jobStateWithStatus(COMPLETED)));
@@ -159,8 +168,8 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
String result = entryNode.compute().execute(
JobTarget.anyNode(node(1).node(), node(2).node()),
- JobDescriptor.builder(concatJobClassName()).units(units()).build(),
- "a", 42);
+ JobDescriptor.builder(concatJobClass()).units(units()).build(),
+ new Object[]{"a", 42});
assertThat(result, is("a42"));
}
@@ -171,7 +180,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
JobExecution<String> execution = entryNode.compute().submit(
JobTarget.anyNode(node(1).node(), node(2).node()),
- JobDescriptor.builder(concatJobClassName()).units(units()).build(),
+ JobDescriptor.builder(concatJobClass()).units(units()).build(),
new Object[]{"a", 42});
assertThat(execution.resultAsync(), willBe("a42"));
@@ -185,7 +194,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
CompletableFuture<String> fut = entryNode.compute().executeAsync(
JobTarget.node(entryNode.node()),
- JobDescriptor.builder(getNodeNameJobClassName()).units(units()).build());
+ JobDescriptor.builder(getNodeNameJobClass()).units(units()).build(), null);
assertThat(fut, willBe(entryNode.name()));
}
@@ -197,7 +206,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
CompletableFuture<String> fut = entryNode.compute().executeAsync(
JobTarget.node(remoteNode.node()),
- JobDescriptor.builder(getNodeNameJobClassName()).units(units()).build());
+ JobDescriptor.builder(getNodeNameJobClass()).units(units()).build(), null);
assertThat(fut, willBe(remoteNode.name()));
}
@@ -208,7 +217,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
IgniteException ex = assertThrows(IgniteException.class, () -> entryNode.compute().execute(
JobTarget.node(entryNode.node()),
- JobDescriptor.builder(failingJobClassName()).units(units()).build()));
+ JobDescriptor.builder(failingJobClassName()).units(units()).build(), null));
assertComputeException(ex, "JobException", "Oops");
}
@@ -219,7 +228,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
JobExecution<String> execution = entryNode.compute().submit(
JobTarget.node(entryNode.node()),
- JobDescriptor.builder(failingJobClassName()).units(units()).build());
+ JobDescriptor.<Object, String>builder(failingJobClassName()).units(units()).build(), null);
ExecutionException ex = assertThrows(ExecutionException.class, () -> execution.resultAsync().get(1, TimeUnit.SECONDS));
@@ -235,7 +244,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
IgniteException ex = assertThrows(IgniteException.class, () -> entryNode.compute().execute(
JobTarget.anyNode(node(1).node(), node(2).node()),
- JobDescriptor.builder(failingJobClassName()).units(units()).build()));
+ JobDescriptor.builder(failingJobClassName()).units(units()).build(), null));
assertComputeException(ex, "JobException", "Oops");
}
@@ -246,7 +255,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
JobExecution<String> execution = entryNode.compute().submit(
JobTarget.anyNode(node(1).node(), node(2).node()),
- JobDescriptor.builder(failingJobClassName()).units(units()).build());
+ JobDescriptor.<Object, String>builder(failingJobClassName()).units(units()).build(), null);
ExecutionException ex = assertThrows(ExecutionException.class, () -> execution.resultAsync().get(1, TimeUnit.SECONDS));
@@ -262,8 +271,8 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
Map<ClusterNode, JobExecution<String>> results = entryNode.compute().submitBroadcast(
Set.of(entryNode.node(), node(1).node(), node(2).node()),
- JobDescriptor.builder(concatJobClassName()).units(units()).build(),
- "a", 42);
+ JobDescriptor.builder(concatJobClass()).units(units()).build(),
+ new Object[] {"a", 42});
assertThat(results, is(aMapWithSize(3)));
for (int i = 0; i < 3; i++) {
@@ -281,7 +290,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
Map<ClusterNode, JobExecution<String>> results = entryNode.compute().submitBroadcast(
Set.of(entryNode.node(), node(1).node(), node(2).node()),
- JobDescriptor.builder(getNodeNameJobClassName()).units(units()).build());
+ JobDescriptor.builder(getNodeNameJobClass()).units(units()).build(), null);
assertThat(results, is(aMapWithSize(3)));
for (int i = 0; i < 3; i++) {
@@ -299,7 +308,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
Map<ClusterNode, JobExecution<String>> results = entryNode.compute().submitBroadcast(
Set.of(entryNode.node(), node(1).node(), node(2).node()),
- JobDescriptor.builder(failingJobClassName()).units(units()).build());
+ JobDescriptor.<Object, String>builder(failingJobClassName()).units(units()).build(), null);
assertThat(results, is(aMapWithSize(3)));
for (int i = 0; i < 3; i++) {
@@ -324,7 +333,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
String actualNodeName = entryNode.compute().execute(
JobTarget.colocated("test", Tuple.create(Map.of("k", 1))),
- JobDescriptor.builder(getNodeNameJobClassName()).units(units()).build());
+ JobDescriptor.builder(getNodeNameJobClass()).units(units()).build(), null);
assertThat(actualNodeName, in(allNodeNames()));
}
@@ -337,7 +346,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
JobExecution<String> execution = entryNode.compute().submit(
JobTarget.colocated("test", Tuple.create(Map.of("k", 1))),
- JobDescriptor.builder(getNodeNameJobClassName()).units(units()).build());
+ JobDescriptor.builder(getNodeNameJobClass()).units(units()).build(), null);
assertThat(execution.resultAsync(), willBe(in(allNodeNames())));
assertThat(execution.stateAsync(), willBe(jobStateWithStatus(COMPLETED)));
@@ -352,8 +361,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
String actualNodeName = node(0).compute().execute(
JobTarget.colocated("test", Tuple.create(Map.of("key_int", 2, "key_str", "4"))),
- JobDescriptor.builder(getNodeNameJobClassName()).units(units()).build());
-
+ JobDescriptor.builder(getNodeNameJobClass()).units(units()).build(), null);
assertThat(actualNodeName, in(allNodeNames()));
}
@@ -364,7 +372,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
var ex = assertThrows(CompletionException.class,
() -> entryNode.compute().submit(
JobTarget.colocated("\"bad-table\"", Tuple.create(Map.of("k", 1))),
- JobDescriptor.builder(getNodeNameJobClassName()).units(units()).build()).resultAsync().join());
+ JobDescriptor.builder(getNodeNameJobClassName()).units(units()).build(), null).resultAsync().join());
assertInstanceOf(TableNotFoundException.class, ex.getCause());
assertThat(ex.getCause().getMessage(), containsString("The table does not exist [name=\"PUBLIC\".\"bad-table\"]"));
@@ -391,7 +399,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
String actualNodeName = entryNode.compute().execute(
JobTarget.colocated("test", 1, Mapper.of(Integer.class)),
- JobDescriptor.builder(getNodeNameJobClassName()).units(units()).build());
+ JobDescriptor.builder(getNodeNameJobClass()).units(units()).build(), null);
assertThat(actualNodeName, in(allNodeNames()));
}
@@ -404,7 +412,7 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
JobExecution<String> execution = entryNode.compute().submit(
JobTarget.colocated("test", 1, Mapper.of(Integer.class)),
- JobDescriptor.builder(getNodeNameJobClassName()).units(units()).build());
+ JobDescriptor.builder(getNodeNameJobClass()).units(units()).build(), null);
assertThat(execution.resultAsync(), willBe(in(allNodeNames())));
assertThat(execution.stateAsync(), willBe(jobStateWithStatus(COMPLETED)));
@@ -448,6 +456,28 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
assertThat(result, is(sumOfNodeNamesLengths));
}
+ @Test
+ void pojoJobArgumentSerialization() {
+ IgniteImpl entryNode = node(0);
+ String address = "127.0.0.1:" + entryNode.clientAddress().port();
+ try (IgniteClient client = IgniteClient.builder().addresses(address).build()) {
+ var argumentPojo = new Pojo("Hey");
+
+ String resultString = client.compute().execute(
+ JobTarget.node(node(1).node()),
+ JobDescriptor.builder(pojoJobClass())
+ .argumentMarshaller(ByteArrayMarshaler.create())
+ .build(),
+ argumentPojo
+ );
+
+ assertThat(resultString, equalTo(argumentPojo.getName()));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
static IgniteImpl node(int i) {
return CLUSTER.node(i);
}
@@ -456,10 +486,27 @@ public abstract class ItComputeBaseTest extends ClusterPerClassIntegrationTest {
return ConcatJob.class.getName();
}
+ static Class<ConcatJob> concatJobClass() {
+ return ConcatJob.class;
+ }
+
+ static String pojoJobClassName() {
+ return PojoJob.class.getName();
+ }
+
+
+ static Class<PojoJob> pojoJobClass() {
+ return PojoJob.class;
+ }
+
private static String getNodeNameJobClassName() {
return GetNodeNameJob.class.getName();
}
+ private static Class<GetNodeNameJob> getNodeNameJobClass() {
+ return GetNodeNameJob.class;
+ }
+
private static String failingJobClassName() {
return FailingJob.class.getName();
}
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeErrorsBaseTest.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeErrorsBaseTest.java
index 82a6092e4a..3347a90392 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeErrorsBaseTest.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeErrorsBaseTest.java
@@ -91,7 +91,7 @@ abstract class ItComputeErrorsBaseTest extends ClusterPerClassIntegrationTest {
// And execute a job
String workerNodeName = compute().execute(
JobTarget.anyNode(nodes),
- JobDescriptor.builder(InteractiveJobs.globalJob().name()).build(),
+ JobDescriptor.<String, String>builder(InteractiveJobs.globalJob().name()).build(),
RETURN_WORKER_NAME.name());
// Then existing node was a worker and executed the job.
@@ -106,7 +106,7 @@ abstract class ItComputeErrorsBaseTest extends ClusterPerClassIntegrationTest {
// Then job fails.
assertThrows(
NodeNotFoundException.class,
- () -> compute().execute(nodes, JobDescriptor.builder(InteractiveJobs.globalJob().name()).build()),
+ () -> compute().execute(nodes, JobDescriptor.builder(InteractiveJobs.globalJob().name()).build(), null),
"None of the specified nodes are present in the cluster: [" + nonExistingNode.name() + "]"
);
}
@@ -122,7 +122,7 @@ abstract class ItComputeErrorsBaseTest extends ClusterPerClassIntegrationTest {
// When broadcast a job
Map<ClusterNode, JobExecution<Object>> executions = compute().submitBroadcast(
- nodes, JobDescriptor.builder(InteractiveJobs.interactiveJobName()).build());
+ nodes, JobDescriptor.builder(InteractiveJobs.interactiveJobName()).build(), null);
// Then one job is alive
assertThat(executions.size(), is(2));
@@ -140,6 +140,10 @@ abstract class ItComputeErrorsBaseTest extends ClusterPerClassIntegrationTest {
private TestingJobExecution<String> executeGlobalInteractiveJob(Set<ClusterNode> nodes) {
return new TestingJobExecution<>(
- compute().submit(JobTarget.anyNode(nodes), JobDescriptor.builder(InteractiveJobs.globalJob().name()).build()));
+ compute().submit(
+ JobTarget.anyNode(nodes),
+ JobDescriptor.<String, String>builder(InteractiveJobs.globalJob().name()).build(),
+ "")
+ );
}
}
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeTestEmbedded.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeTestEmbedded.java
index ee98977181..2d78e8d907 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeTestEmbedded.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeTestEmbedded.java
@@ -65,6 +65,7 @@ import org.apache.ignite.lang.IgniteException;
import org.apache.ignite.network.ClusterNode;
import org.apache.ignite.table.KeyValueView;
import org.apache.ignite.table.Table;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -125,6 +126,7 @@ class ItComputeTestEmbedded extends ItComputeBaseTest {
}
@Test
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-22577")
void cancelsJobRemotely() {
IgniteImpl entryNode = node(0);
@@ -151,6 +153,7 @@ class ItComputeTestEmbedded extends ItComputeBaseTest {
}
@Test
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-22577")
void changeExecutingJobPriorityRemotely() {
IgniteImpl entryNode = node(0);
@@ -212,11 +215,12 @@ class ItComputeTestEmbedded extends ItComputeBaseTest {
JobDescriptor job = JobDescriptor.builder(WaitLatchJob.class).units(units()).build();
// Start 1 task in executor with 1 thread
- JobExecution<String> execution1 = entryNode.compute().submit(jobTarget, job, new Object[]{countDownLatch});
+ JobExecution<String> execution1 = entryNode.compute().submit(jobTarget, job, countDownLatch);
+
await().until(execution1::stateAsync, willBe(jobStateWithStatus(EXECUTING)));
// Start one more task
- JobExecution<String> execution2 = entryNode.compute().submit(jobTarget, job, new Object[]{new CountDownLatch(1)});
+ JobExecution<String> execution2 = entryNode.compute().submit(jobTarget, job, new CountDownLatch(1));
await().until(execution2::stateAsync, willBe(jobStateWithStatus(QUEUED)));
// Start third task it should be before task2 in the queue due to higher priority in options
@@ -316,7 +320,7 @@ class ItComputeTestEmbedded extends ItComputeBaseTest {
assertDoesNotThrow(() -> entryNode.compute().execute(
JobTarget.node(targetNode.node()),
- JobDescriptor.builder(PerformSyncKvGetPutJob.class).build()));
+ JobDescriptor.builder(PerformSyncKvGetPutJob.class).build(), null));
}
@Test
@@ -324,7 +328,7 @@ class ItComputeTestEmbedded extends ItComputeBaseTest {
IgniteImpl entryNode = node(0);
Map<ClusterNode, Object> results = entryNode.compute()
- .executeBroadcast(new HashSet<>(entryNode.clusterNodes()), JobDescriptor.builder(NullReturningJob.class).build());
+ .executeBroadcast(new HashSet<>(entryNode.clusterNodes()), JobDescriptor.builder(NullReturningJob.class).build(), null);
assertThat(results.keySet(), equalTo(new HashSet<>(entryNode.clusterNodes())));
assertThat(new HashSet<>(results.values()), contains(nullValue()));
@@ -334,8 +338,9 @@ class ItComputeTestEmbedded extends ItComputeBaseTest {
void executesNullReturningJobViaAsyncBroadcast() {
IgniteImpl entryNode = node(0);
- CompletableFuture<Map<ClusterNode, Object>> resultsFuture = entryNode.compute()
- .executeBroadcastAsync(new HashSet<>(entryNode.clusterNodes()), JobDescriptor.builder(NullReturningJob.class).build());
+ CompletableFuture<Map<ClusterNode, Object>> resultsFuture = entryNode.compute().executeBroadcastAsync(
+ new HashSet<>(entryNode.clusterNodes()), JobDescriptor.builder(NullReturningJob.class).build(), null
+ );
assertThat(resultsFuture, willCompleteSuccessfully());
Map<ClusterNode, Object> results = resultsFuture.join();
@@ -349,7 +354,7 @@ class ItComputeTestEmbedded extends ItComputeBaseTest {
Map<ClusterNode, JobExecution<Object>> executionsMap = entryNode.compute().submitBroadcast(
new HashSet<>(entryNode.clusterNodes()),
- JobDescriptor.builder(NullReturningJob.class.getName()).build());
+ JobDescriptor.builder(NullReturningJob.class.getName()).build(), null);
assertThat(executionsMap.keySet(), equalTo(new HashSet<>(entryNode.clusterNodes())));
List<JobExecution<Object>> executions = new ArrayList<>(executionsMap.values());
@@ -365,18 +370,18 @@ class ItComputeTestEmbedded extends ItComputeBaseTest {
return IntStream.range(0, initialNodes()).mapToObj(Arguments::of);
}
- private static class CustomFailingJob implements ComputeJob<String> {
+ private static class CustomFailingJob implements ComputeJob<Throwable, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
- throw ExceptionUtils.sneakyThrow((Throwable) args[0]);
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Throwable th) {
+ throw ExceptionUtils.sneakyThrow(th);
}
}
- private static class WaitLatchJob implements ComputeJob<String> {
+ private static class WaitLatchJob implements ComputeJob<CountDownLatch, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, CountDownLatch latch) {
try {
- ((CountDownLatch) args[0]).await();
+ latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
@@ -384,13 +389,13 @@ class ItComputeTestEmbedded extends ItComputeBaseTest {
}
}
- private static class WaitLatchThrowExceptionOnFirstExecutionJob implements ComputeJob<String> {
+ private static class WaitLatchThrowExceptionOnFirstExecutionJob implements ComputeJob<CountDownLatch, String> {
static final AtomicInteger counter = new AtomicInteger(0);
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, CountDownLatch latch) {
try {
- ((CountDownLatch) args[0]).await();
+ latch.await();
if (counter.incrementAndGet() == 1) {
throw new RuntimeException();
}
@@ -401,9 +406,9 @@ class ItComputeTestEmbedded extends ItComputeBaseTest {
}
}
- private static class PerformSyncKvGetPutJob implements ComputeJob<Void> {
+ private static class PerformSyncKvGetPutJob implements ComputeJob<Void, Void> {
@Override
- public CompletableFuture<Void> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<Void> executeAsync(JobExecutionContext context, Void input) {
Table table = context.ignite().tables().table("test");
KeyValueView<Integer, Integer> view = table.keyValueView(Integer.class, Integer.class);
@@ -414,9 +419,9 @@ class ItComputeTestEmbedded extends ItComputeBaseTest {
}
}
- private static class NullReturningJob implements ComputeJob<Void> {
+ private static class NullReturningJob implements ComputeJob<Object, Object> {
@Override
- public CompletableFuture<Void> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<Object> executeAsync(JobExecutionContext context, Object input) {
return null;
}
}
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeTestStandalone.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeTestStandalone.java
index 794ccbacce..8a28baadba 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeTestStandalone.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItComputeTestStandalone.java
@@ -106,8 +106,8 @@ class ItComputeTestStandalone extends ItComputeBaseTest {
List<DeploymentUnit> nonExistingUnits = List.of(new DeploymentUnit("non-existing", "1.0.0"));
CompletableFuture<String> result = entryNode.compute().executeAsync(
JobTarget.node(entryNode.node()),
- JobDescriptor.builder(concatJobClassName()).units(nonExistingUnits).build(),
- "a", 42);
+ JobDescriptor.<Object[], String>builder(concatJobClassName()).units(nonExistingUnits).build(),
+ new Object[]{"a", 42});
CompletionException ex0 = assertThrows(CompletionException.class, result::join);
@@ -128,13 +128,13 @@ class ItComputeTestStandalone extends ItComputeBaseTest {
deployJar(entryNode, firstVersion.name(), firstVersion.version(), "ignite-unit-test-job1-1.0-SNAPSHOT.jar");
JobDescriptor job = JobDescriptor.builder("org.apache.ignite.internal.compute.UnitJob").units(jobUnits).build();
- CompletableFuture<Integer> result1 = entryNode.compute().executeAsync(JobTarget.node(entryNode.node()), job);
+ CompletableFuture<Integer> result1 = entryNode.compute().executeAsync(JobTarget.node(entryNode.node()), job, null);
assertThat(result1, willBe(1));
DeploymentUnit secondVersion = new DeploymentUnit("latest-unit", Version.parseVersion("1.0.1"));
deployJar(entryNode, secondVersion.name(), secondVersion.version(), "ignite-unit-test-job2-1.0-SNAPSHOT.jar");
- CompletableFuture<String> result2 = entryNode.compute().executeAsync(JobTarget.node(entryNode.node()), job);
+ CompletableFuture<String> result2 = entryNode.compute().executeAsync(JobTarget.node(entryNode.node()), job, null);
assertThat(result2, willBe("Hello World!"));
}
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItExecutionsCleanerTest.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItExecutionsCleanerTest.java
index e4e66b2604..552b9e8a71 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItExecutionsCleanerTest.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItExecutionsCleanerTest.java
@@ -246,7 +246,8 @@ class ItExecutionsCleanerTest extends ClusterPerClassIntegrationTest {
private static TestingJobExecution<Object> submit(Set<ClusterNode> nodes) {
IgniteCompute igniteCompute = CLUSTER.node(0).compute();
- return new TestingJobExecution<>(
- igniteCompute.submit(JobTarget.anyNode(nodes), JobDescriptor.builder(InteractiveJobs.globalJob().name()).build()));
+ return new TestingJobExecution<>(igniteCompute.submit(
+ JobTarget.anyNode(nodes), JobDescriptor.builder(InteractiveJobs.globalJob().name()).build(), null
+ ));
}
}
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItFailoverCandidateNotFoundTest.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItFailoverCandidateNotFoundTest.java
index e1cd0e1ce6..2ac4654c04 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItFailoverCandidateNotFoundTest.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItFailoverCandidateNotFoundTest.java
@@ -97,6 +97,6 @@ public class ItFailoverCandidateNotFoundTest extends ClusterPerTestIntegrationTe
private static TestingJobExecution<String> executeGlobalInteractiveJob(IgniteCompute compute, Set<ClusterNode> nodes) {
return new TestingJobExecution<>(
- compute.submit(JobTarget.anyNode(nodes), JobDescriptor.builder(InteractiveJobs.globalJob().name()).build()));
+ compute.submit(JobTarget.anyNode(nodes), JobDescriptor.builder(InteractiveJobs.globalJob().jobClass()).build(), null));
}
}
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItMapReduceTest.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItMapReduceTest.java
index b206938a8a..5ecaa96c02 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItMapReduceTest.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItMapReduceTest.java
@@ -68,7 +68,9 @@ class ItMapReduceTest extends ClusterPerClassIntegrationTest {
IgniteImpl entryNode = CLUSTER.node(0);
// Given running task.
- TaskExecution<List<String>> taskExecution = entryNode.compute().submitMapReduce(List.of(), InteractiveTasks.GlobalApi.name());
+ TaskExecution<List<String>> taskExecution = entryNode.compute().submitMapReduce(
+ List.of(), InteractiveTasks.GlobalApi.name(), null
+ );
TestingJobExecution<List<String>> testExecution = new TestingJobExecution<>(new TaskToJobExecutionWrapper<>(taskExecution));
testExecution.assertExecuting();
InteractiveTasks.GlobalApi.assertAlive();
@@ -115,7 +117,7 @@ class ItMapReduceTest extends ClusterPerClassIntegrationTest {
IgniteImpl entryNode = CLUSTER.node(0);
// Given running task.
- TaskExecution<List<String>> taskExecution = startTask(entryNode);
+ TaskExecution<List<String>> taskExecution = startTask(entryNode, null);
// Save state before split.
TaskState stateBeforeSplit = taskExecution.stateAsync().join();
@@ -159,7 +161,7 @@ class ItMapReduceTest extends ClusterPerClassIntegrationTest {
IgniteImpl entryNode = CLUSTER.node(0);
// Given running task.
- TaskExecution<List<String>> taskExecution = startTask(entryNode);
+ TaskExecution<List<String>> taskExecution = startTask(entryNode, null);
// Save state before split.
TaskState stateBeforeSplit = taskExecution.stateAsync().join();
@@ -179,7 +181,9 @@ class ItMapReduceTest extends ClusterPerClassIntegrationTest {
IgniteImpl entryNode = CLUSTER.node(0);
// Given running task.
- TaskExecution<List<String>> taskExecution = entryNode.compute().submitMapReduce(List.of(), InteractiveTasks.GlobalApi.name());
+ TaskExecution<List<String>> taskExecution = entryNode.compute().submitMapReduce(
+ List.of(), InteractiveTasks.GlobalApi.name(), null
+ );
TestingJobExecution<List<String>> testExecution = new TestingJobExecution<>(new TaskToJobExecutionWrapper<>(taskExecution));
testExecution.assertExecuting();
InteractiveTasks.GlobalApi.assertAlive();
@@ -208,7 +212,7 @@ class ItMapReduceTest extends ClusterPerClassIntegrationTest {
IgniteImpl entryNode = CLUSTER.node(0);
// Given running task.
- TaskExecution<List<String>> taskExecution = startTask(entryNode);
+ TaskExecution<List<String>> taskExecution = startTask(entryNode, null);
// Save state before split.
TaskState stateBeforeSplit = taskExecution.stateAsync().join();
@@ -235,8 +239,10 @@ class ItMapReduceTest extends ClusterPerClassIntegrationTest {
IgniteImpl entryNode = CLUSTER.node(0);
// Given running task.
- String arg = cooperativeCancel ? "NO_INTERRUPT" : "";
- TaskExecution<List<String>> taskExecution = entryNode.compute().submitMapReduce(List.of(), InteractiveTasks.GlobalApi.name(), arg);
+ String arg = cooperativeCancel ? "NO_INTERRUPT" : null;
+ TaskExecution<List<String>> taskExecution = entryNode.compute().submitMapReduce(
+ List.of(), InteractiveTasks.GlobalApi.name(), arg
+ );
TestingJobExecution<List<String>> testExecution = new TestingJobExecution<>(new TaskToJobExecutionWrapper<>(taskExecution));
testExecution.assertExecuting();
InteractiveTasks.GlobalApi.assertAlive();
@@ -266,7 +272,7 @@ class ItMapReduceTest extends ClusterPerClassIntegrationTest {
assertThat(taskExecution.cancelAsync(), willBe(false));
}
- private static TaskExecution<List<String>> startTask(IgniteImpl entryNode, Object... args) throws InterruptedException {
+ private static TaskExecution<List<String>> startTask(IgniteImpl entryNode, String args) throws InterruptedException {
TaskExecution<List<String>> taskExecution = entryNode.compute().submitMapReduce(List.of(), InteractiveTasks.GlobalApi.name(), args);
new TestingJobExecution<>(new TaskToJobExecutionWrapper<>(taskExecution)).assertExecuting();
InteractiveTasks.GlobalApi.assertAlive();
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItWorkerShutdownTest.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItWorkerShutdownTest.java
index a83b9a4fe4..8bfc785eac 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItWorkerShutdownTest.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/ItWorkerShutdownTest.java
@@ -216,7 +216,7 @@ public abstract class ItWorkerShutdownTest extends ClusterPerTestIntegrationTest
// When start broadcast job.
Map<ClusterNode, JobExecution<Object>> executions = compute(entryNode).submitBroadcast(
clusterNodesByNames(workerCandidates(node(0), node(1), node(2))),
- JobDescriptor.builder(InteractiveJobs.interactiveJobName()).build());
+ JobDescriptor.builder(InteractiveJobs.interactiveJobName()).build(), null);
// Then all three jobs are alive.
assertThat(executions.size(), is(3));
@@ -293,7 +293,8 @@ public abstract class ItWorkerShutdownTest extends ClusterPerTestIntegrationTest
TestingJobExecution<Object> execution = new TestingJobExecution<>(
compute(entryNode).submit(
JobTarget.colocated(TABLE_NAME, Tuple.create(1).set("K", 1)),
- JobDescriptor.builder(InteractiveJobs.globalJob().name()).build()));
+ JobDescriptor.builder(InteractiveJobs.globalJob().name()).build(),
+ null));
// Then the job is alive.
InteractiveJobs.globalJob().assertAlive();
@@ -364,7 +365,7 @@ public abstract class ItWorkerShutdownTest extends ClusterPerTestIntegrationTest
return new TestingJobExecution<>(
compute(entryNode).submit(
JobTarget.anyNode(clusterNodesByNames(nodes)),
- JobDescriptor.builder(InteractiveJobs.globalJob().name()).build())
+ JobDescriptor.builder(InteractiveJobs.globalJob().jobClass()).build(), null)
);
}
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/threading/ItComputeApiThreadingTest.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/threading/ItComputeApiThreadingTest.java
index 46c9388490..4e2b9f49b2 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/threading/ItComputeApiThreadingTest.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/threading/ItComputeApiThreadingTest.java
@@ -141,27 +141,30 @@ class ItComputeApiThreadingTest extends ClusterPerClassIntegrationTest {
return Set.of(CLUSTER.node(1).node());
}
- private static class NoOpJob implements ComputeJob<String> {
+ private static class NoOpJob implements ComputeJob<Void, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Void input) {
return completedFuture("ok");
}
}
private enum ComputeAsyncOperation {
- EXECUTE_ASYNC(compute -> compute.executeAsync(JobTarget.anyNode(justNonEntryNode()), JobDescriptor.builder(NoOpJob.class).build())),
-
+ EXECUTE_ASYNC(compute -> compute.executeAsync(
+ JobTarget.anyNode(justNonEntryNode()),
+ JobDescriptor.builder(NoOpJob.class).build(),
+ null)),
EXECUTE_COLOCATED_BY_TUPLE_ASYNC(compute ->
compute.executeAsync(
JobTarget.colocated(TABLE_NAME, KEY_TUPLE),
- JobDescriptor.builder(NoOpJob.class).build())),
-
+ JobDescriptor.builder(NoOpJob.class).build(), null)),
EXECUTE_COLOCATED_BY_KEY_ASYNC(compute ->
compute.executeAsync(
JobTarget.colocated(TABLE_NAME, KEY, Mapper.of(Integer.class)),
- JobDescriptor.builder(NoOpJob.class).build())),
+ JobDescriptor.builder(NoOpJob.class).build(),
- EXECUTE_BROADCAST_ASYNC(compute -> compute.executeBroadcastAsync(justNonEntryNode(), JobDescriptor.builder(NoOpJob.class).build()));
+ null)),
+ EXECUTE_BROADCAST_ASYNC(compute -> compute.executeBroadcastAsync(justNonEntryNode(), JobDescriptor.builder(NoOpJob.class).build(),
+ null));
private final Function<IgniteCompute, CompletableFuture<?>> action;
@@ -175,19 +178,19 @@ class ItComputeApiThreadingTest extends ClusterPerClassIntegrationTest {
}
private enum ComputeSubmitOperation {
- SUBMIT(compute -> compute.submit(JobTarget.anyNode(justNonEntryNode()), JobDescriptor.builder(NoOpJob.class).build())),
+ SUBMIT(compute -> compute.submit(JobTarget.anyNode(justNonEntryNode()), JobDescriptor.builder(NoOpJob.class).build(), null)),
SUBMIT_COLOCATED_BY_TUPLE(compute -> compute.submit(
JobTarget.colocated(TABLE_NAME, KEY_TUPLE),
- JobDescriptor.builder(NoOpJob.class).build())),
-
+ JobDescriptor.builder(NoOpJob.class).build(),
+ null)),
SUBMIT_COLOCATED_BY_KEY(compute -> compute.submit(
JobTarget.colocated(TABLE_NAME, KEY, Mapper.of(Integer.class)),
- JobDescriptor.builder(NoOpJob.class).build())
+ JobDescriptor.builder(NoOpJob.class).build(), null)
),
SUBMIT_BROADCAST(compute -> compute
- .submitBroadcast(justNonEntryNode(), JobDescriptor.builder(NoOpJob.class).build())
+ .submitBroadcast(justNonEntryNode(), JobDescriptor.builder(NoOpJob.class).build(), null)
.values().iterator().next()
);
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/utils/InteractiveJobs.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/utils/InteractiveJobs.java
index 25d5022ea5..4cc1697a17 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/utils/InteractiveJobs.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/utils/InteractiveJobs.java
@@ -155,7 +155,7 @@ public final class InteractiveJobs {
/**
* Interactive job that communicates via {@link #GLOBAL_CHANNEL} and {@link #GLOBAL_SIGNALS}.
*/
- private static class GlobalInteractiveJob implements ComputeJob<String> {
+ public static class GlobalInteractiveJob implements ComputeJob<String, String> {
private static Signal listenSignal() {
try {
return GLOBAL_SIGNALS.take();
@@ -165,7 +165,7 @@ public final class InteractiveJobs {
}
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, String args) {
RUNNING_INTERACTIVE_JOBS_CNT.incrementAndGet();
offerArgsAsSignals(args);
@@ -198,18 +198,16 @@ public final class InteractiveJobs {
/**
* If any of the args are strings, convert them to signals and offer them to the job.
*
- * @param args Job args.
+ * @param arg Job args.
*/
- private static void offerArgsAsSignals(Object[] args) {
- for (Object arg : args) {
- if (arg instanceof String) {
- String signal = (String) arg;
- try {
- GLOBAL_SIGNALS.offer(Signal.valueOf(signal));
- } catch (IllegalArgumentException ignored) {
- // Ignore non-signal strings
- }
- }
+ private static void offerArgsAsSignals(String arg) {
+ if (arg == null) {
+ return;
+ }
+ try {
+ GLOBAL_SIGNALS.offer(Signal.valueOf(arg));
+ } catch (IllegalArgumentException ignored) {
+ // Ignore non-signal strings
}
}
}
@@ -218,7 +216,7 @@ public final class InteractiveJobs {
* Interactive job that communicates via {@link #NODE_CHANNELS} and {@link #NODE_SIGNALS}. Also, keeps track of how many times it was
* executed via {@link #RUNNING_INTERACTIVE_JOBS_CNT}.
*/
- private static class InteractiveJob implements ComputeJob<String> {
+ private static class InteractiveJob implements ComputeJob<Object[], String> {
private static Signal listenSignal(BlockingQueue<Signal> channel) {
try {
return channel.take();
@@ -414,5 +412,9 @@ public final class InteractiveJobs {
public String name() {
return GlobalInteractiveJob.class.getName();
}
+
+ public Class<GlobalInteractiveJob> jobClass() {
+ return GlobalInteractiveJob.class;
+ }
}
}
diff --git a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/utils/InteractiveTasks.java b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/utils/InteractiveTasks.java
index d9c65ed1d3..8aec9bb9c8 100644
--- a/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/utils/InteractiveTasks.java
+++ b/modules/compute/src/integrationTest/java/org/apache/ignite/internal/compute/utils/InteractiveTasks.java
@@ -132,17 +132,15 @@ public final class InteractiveTasks {
/**
* If any of the args are strings, convert them to signals and offer them to the job.
*
- * @param args Job args.
+ * @param arg Job args.
*/
- private static void offerArgsAsSignals(Object... args) {
- for (Object arg : args) {
- if (arg instanceof String) {
- String signal = (String) arg;
- try {
- GLOBAL_SIGNALS.offer(Signal.valueOf(signal));
- } catch (IllegalArgumentException ignored) {
- // Ignore non-signal strings
- }
+ private static void offerArgsAsSignals(Object arg) {
+ if (arg instanceof String) {
+ String signal = (String) arg;
+ try {
+ GLOBAL_SIGNALS.offer(Signal.valueOf(signal));
+ } catch (IllegalArgumentException ignored) {
+ // Ignore non-signal strings
}
}
}
@@ -150,7 +148,7 @@ public final class InteractiveTasks {
/**
* Interactive map reduce task that communicates via {@link #GLOBAL_CHANNEL} and {@link #GLOBAL_SIGNALS}.
*/
- private static class GlobalInteractiveMapReduceTask implements MapReduceTask<List<String>> {
+ private static class GlobalInteractiveMapReduceTask implements MapReduceTask<String, Object, Object, List<String>> {
// When listening for signal is interrupted, if this flag is true, then corresponding method will throw exception,
// otherwise it will clean the interrupted status.
private boolean throwExceptionOnInterruption = true;
@@ -171,15 +169,12 @@ public final class InteractiveTasks {
}
@Override
- public CompletableFuture<List<MapReduceJob>> splitAsync(TaskExecutionContext context, Object... args) {
+ public CompletableFuture<List<MapReduceJob<Object, Object>>> splitAsync(TaskExecutionContext context, String args) {
RUNNING_GLOBAL_SPLIT_CNT.incrementAndGet();
offerArgsAsSignals(args);
- for (Object arg : args) {
- if (NO_INTERRUPT_ARG_NAME.equals(arg)) {
- throwExceptionOnInterruption = false;
- break;
- }
+ if (NO_INTERRUPT_ARG_NAME.equals(args)) {
+ throwExceptionOnInterruption = false;
}
try {
@@ -213,7 +208,7 @@ public final class InteractiveTasks {
}
@Override
- public CompletableFuture<List<String>> reduceAsync(TaskExecutionContext context, Map<UUID, ?> results) {
+ public CompletableFuture<List<String>> reduceAsync(TaskExecutionContext context, Map<UUID, Object> results) {
RUNNING_GLOBAL_REDUCE_CNT.incrementAndGet();
try {
while (true) {
diff --git a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/ConcatJob.java b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/ConcatJob.java
index b235ad0fea..9cf96f4745 100644
--- a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/ConcatJob.java
+++ b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/ConcatJob.java
@@ -26,11 +26,12 @@ import org.apache.ignite.compute.ComputeJob;
import org.apache.ignite.compute.JobExecutionContext;
/** Compute job that concatenates the string representation of its arguments. */
-public class ConcatJob implements ComputeJob<String> {
+public class ConcatJob implements ComputeJob<Object[], String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
- return completedFuture(Arrays.stream(args)
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... input) {
+ return completedFuture(Arrays.stream(input)
.map(Object::toString)
.collect(Collectors.joining()));
}
}
+
diff --git a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/FailingJob.java b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/FailingJob.java
index 20497cf23d..22a1020380 100644
--- a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/FailingJob.java
+++ b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/FailingJob.java
@@ -22,9 +22,9 @@ import org.apache.ignite.compute.ComputeJob;
import org.apache.ignite.compute.JobExecutionContext;
/** Compute job that always fails with the {@link JobException}. */
-public class FailingJob implements ComputeJob<String> {
+public class FailingJob implements ComputeJob<Void, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Void input) {
throw new JobException("Oops", new Exception());
}
}
diff --git a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/GetNodeNameJob.java b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/GetNodeNameJob.java
index 226fbf83b3..fd324e4b50 100644
--- a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/GetNodeNameJob.java
+++ b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/GetNodeNameJob.java
@@ -24,9 +24,9 @@ import org.apache.ignite.compute.ComputeJob;
import org.apache.ignite.compute.JobExecutionContext;
/** Compute job that returns the node name. */
-public class GetNodeNameJob implements ComputeJob<String> {
+public class GetNodeNameJob implements ComputeJob<Void, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Void input) {
return completedFuture(context.ignite().name());
}
}
diff --git a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/MapReduce.java b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/MapReduce.java
index 9438f0d2f4..849693bffd 100644
--- a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/MapReduce.java
+++ b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/MapReduce.java
@@ -33,14 +33,14 @@ import org.apache.ignite.compute.task.TaskExecutionContext;
import org.apache.ignite.deployment.DeploymentUnit;
/** Map reduce task which runs a {@link GetNodeNameJob} on each node and computes a sum of length of all node names. */
-public class MapReduce implements MapReduceTask<Integer> {
+public class MapReduce implements MapReduceTask<List<DeploymentUnit>, Void, String, Integer> {
@Override
- public CompletableFuture<List<MapReduceJob>> splitAsync(TaskExecutionContext taskContext, Object... args) {
- List<DeploymentUnit> deploymentUnits = (List<DeploymentUnit>) args[0];
-
+ public CompletableFuture<List<MapReduceJob<Void, String>>> splitAsync(
+ TaskExecutionContext taskContext, List<DeploymentUnit> deploymentUnits) {
return taskContext.ignite().clusterNodesAsync().thenApply(nodes -> nodes.stream().map(node ->
- MapReduceJob.builder()
- .jobDescriptor(JobDescriptor.builder(GetNodeNameJob.class)
+ MapReduceJob.<Void, String>builder()
+ .jobDescriptor(
+ JobDescriptor.builder(GetNodeNameJob.class)
.units(deploymentUnits)
.options(JobExecutionOptions.builder()
.maxRetries(10)
@@ -53,7 +53,7 @@ public class MapReduce implements MapReduceTask<Integer> {
}
@Override
- public CompletableFuture<Integer> reduceAsync(TaskExecutionContext taskContext, Map<UUID, ?> results) {
+ public CompletableFuture<Integer> reduceAsync(TaskExecutionContext taskContext, Map<UUID, String> results) {
return completedFuture(results.values().stream()
.map(String.class::cast)
.map(String::length)
diff --git a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/NonEmptyConstructorJob.java b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/NonEmptyConstructorJob.java
index 01721fd2fa..cc36a8b3ad 100644
--- a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/NonEmptyConstructorJob.java
+++ b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/NonEmptyConstructorJob.java
@@ -24,13 +24,13 @@ import org.apache.ignite.compute.ComputeJob;
import org.apache.ignite.compute.JobExecutionContext;
/** A compute job without default constructor. */
-public class NonEmptyConstructorJob implements ComputeJob<String> {
+public class NonEmptyConstructorJob implements ComputeJob<Void, String> {
private NonEmptyConstructorJob(String s) {
}
/** {@inheritDoc} */
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Void input) {
return completedFuture("");
}
}
diff --git a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/SleepJob.java b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/Pojo.java
similarity index 51%
copy from modules/compute/src/jobs/java/org/apache/ignite/internal/compute/SleepJob.java
copy to modules/compute/src/jobs/java/org/apache/ignite/internal/compute/Pojo.java
index 9c8c2592bb..9e335dbd2c 100644
--- a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/SleepJob.java
+++ b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/Pojo.java
@@ -17,20 +17,46 @@
package org.apache.ignite.internal.compute;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-import org.apache.ignite.compute.ComputeJob;
-import org.apache.ignite.compute.JobExecutionContext;
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * Pojo that is used to test default java serialization.
+ */
+public class Pojo implements Serializable {
+ private String name;
+
+ public Pojo(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
-/** Compute job that sleeps for a number of milliseconds passed in the argument. */
-public class SleepJob implements ComputeJob<Void> {
@Override
- public CompletableFuture<Void> executeAsync(JobExecutionContext jobExecutionContext, Object... args) {
- try {
- TimeUnit.SECONDS.sleep((Long) args[0]);
- return null;
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
+ public String toString() {
+ return "Pojo [name=" + name + "]";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
}
+ Pojo pojo = (Pojo) o;
+ return Objects.equals(name, pojo.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name);
}
}
diff --git a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/NonEmptyConstructorJob.java b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/PojoJob.java
similarity index 64%
copy from modules/compute/src/jobs/java/org/apache/ignite/internal/compute/NonEmptyConstructorJob.java
copy to modules/compute/src/jobs/java/org/apache/ignite/internal/compute/PojoJob.java
index 01721fd2fa..1735e99d51 100644
--- a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/NonEmptyConstructorJob.java
+++ b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/PojoJob.java
@@ -17,20 +17,30 @@
package org.apache.ignite.internal.compute;
-import static java.util.concurrent.CompletableFuture.completedFuture;
-
import java.util.concurrent.CompletableFuture;
import org.apache.ignite.compute.ComputeJob;
import org.apache.ignite.compute.JobExecutionContext;
+import org.apache.ignite.marshaling.ByteArrayMarshaler;
+import org.apache.ignite.marshaling.Marshaler;
-/** A compute job without default constructor. */
-public class NonEmptyConstructorJob implements ComputeJob<String> {
- private NonEmptyConstructorJob(String s) {
+/**
+ * Pojo job.
+ */
+public class PojoJob implements ComputeJob<Pojo, String> {
+ /**
+ * Executes this job.
+ *
+ * @param context The execution context.
+ * @param pojo Job arguments.
+ * @return Future with the same pojo that was passed as an argument.
+ */
+ @Override
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Pojo pojo) {
+ return CompletableFuture.completedFuture(pojo.getName());
}
- /** {@inheritDoc} */
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
- return completedFuture("");
+ public Marshaler<Pojo, byte[]> inputMarshaler() {
+ return ByteArrayMarshaler.create();
}
}
diff --git a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/SleepJob.java b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/SleepJob.java
index 9c8c2592bb..605baa7929 100644
--- a/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/SleepJob.java
+++ b/modules/compute/src/jobs/java/org/apache/ignite/internal/compute/SleepJob.java
@@ -23,11 +23,11 @@ import org.apache.ignite.compute.ComputeJob;
import org.apache.ignite.compute.JobExecutionContext;
/** Compute job that sleeps for a number of milliseconds passed in the argument. */
-public class SleepJob implements ComputeJob<Void> {
+public class SleepJob implements ComputeJob<Long, Void> {
@Override
- public CompletableFuture<Void> executeAsync(JobExecutionContext jobExecutionContext, Object... args) {
+ public CompletableFuture<Void> executeAsync(JobExecutionContext jobExecutionContext, Long timeout) {
try {
- TimeUnit.SECONDS.sleep((Long) args[0]);
+ TimeUnit.SECONDS.sleep(timeout);
return null;
} catch (InterruptedException e) {
throw new RuntimeException(e);
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/AntiHijackIgniteCompute.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/AntiHijackIgniteCompute.java
index 92627408bd..7d50e506d8 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/AntiHijackIgniteCompute.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/AntiHijackIgniteCompute.java
@@ -50,20 +50,20 @@ public class AntiHijackIgniteCompute implements IgniteCompute, Wrapper {
}
@Override
- public <R> JobExecution<R> submit(JobTarget target, JobDescriptor descriptor, Object... args) {
+ public <T, R> JobExecution<R> submit(JobTarget target, JobDescriptor<T, R> descriptor, T args) {
return preventThreadHijack(compute.submit(target, descriptor, args));
}
@Override
- public <R> R execute(JobTarget target, JobDescriptor descriptor, Object... args) {
+ public <T, R> R execute(JobTarget target, JobDescriptor<T, R> descriptor, T args) {
return compute.execute(target, descriptor, args);
}
@Override
- public <R> Map<ClusterNode, JobExecution<R>> submitBroadcast(
+ public <T, R> Map<ClusterNode, JobExecution<R>> submitBroadcast(
Set<ClusterNode> nodes,
- JobDescriptor descriptor,
- Object... args
+ JobDescriptor<T, R> descriptor,
+ T args
) {
Map<ClusterNode, JobExecution<R>> results = compute.submitBroadcast(nodes, descriptor, args);
@@ -72,16 +72,16 @@ public class AntiHijackIgniteCompute implements IgniteCompute, Wrapper {
}
@Override
- public <R> TaskExecution<R> submitMapReduce(List<DeploymentUnit> units, String taskClassName, Object... args) {
+ public <T, R> TaskExecution<R> submitMapReduce(List<DeploymentUnit> units, String taskClassName, T args) {
return new AntiHijackTaskExecution<>(compute.submitMapReduce(units, taskClassName, args), asyncContinuationExecutor);
}
@Override
- public <R> R executeMapReduce(List<DeploymentUnit> units, String taskClassName, Object... args) {
+ public <T, R> R executeMapReduce(List<DeploymentUnit> units, String taskClassName, T args) {
return compute.executeMapReduce(units, taskClassName, args);
}
- private <R> JobExecution<R> preventThreadHijack(JobExecution<R> execution) {
+ private <T, R> JobExecution<R> preventThreadHijack(JobExecution<R> execution) {
return new AntiHijackJobExecution<>(execution, asyncContinuationExecutor);
}
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeComponent.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeComponent.java
index 86d1bb76f3..bdff6c0164 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeComponent.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeComponent.java
@@ -37,18 +37,19 @@ public interface ComputeComponent extends IgniteComponent {
/**
* Executes a job of the given class on the current node.
*
+ *
* @param options Job execution options.
* @param units Deployment units which will be loaded for execution.
* @param jobClassName Name of the job class.
- * @param args Job args.
+ * @param arg Job args.
* @param <R> Job result type.
* @return Job execution object.
*/
- <R> JobExecution<R> executeLocally(
+ <T, R> JobExecution<R> executeLocally(
ExecutionOptions options,
List<DeploymentUnit> units,
String jobClassName,
- Object... args
+ T arg
);
/**
@@ -56,16 +57,16 @@ public interface ComputeComponent extends IgniteComponent {
*
* @param units Deployment units which will be loaded for execution.
* @param jobClassName Name of the job class.
- * @param args Job args.
+ * @param arg Job args.
* @param <R> Job result type.
* @return Job execution object.
*/
- default <R> JobExecution<R> executeLocally(
+ default <T, R> JobExecution<R> executeLocally(
List<DeploymentUnit> units,
String jobClassName,
- Object... args
+ T arg
) {
- return executeLocally(ExecutionOptions.DEFAULT, units, jobClassName, args);
+ return executeLocally(ExecutionOptions.DEFAULT, units, jobClassName, arg);
}
/**
@@ -75,16 +76,16 @@ public interface ComputeComponent extends IgniteComponent {
* @param remoteNode Remote node name.
* @param units Deployment units which will be loaded for execution.
* @param jobClassName Name of the job class.
- * @param args Job args.
+ * @param arg Job args.
* @param <R> Job result type.
* @return Job execution object.
*/
- <R> JobExecution<R> executeRemotely(
+ <T, R> JobExecution<R> executeRemotely(
ExecutionOptions options,
ClusterNode remoteNode,
List<DeploymentUnit> units,
String jobClassName,
- Object... args
+ T arg
);
/**
@@ -93,17 +94,17 @@ public interface ComputeComponent extends IgniteComponent {
* @param remoteNode Remote node name.
* @param units Deployment units which will be loaded for execution.
* @param jobClassName Name of the job class.
- * @param args Job args.
+ * @param arg Job args.
* @param <R> Job result type.
* @return Job execution object.
*/
- default <R> JobExecution<R> executeRemotely(
+ default <T, R> JobExecution<R> executeRemotely(
ClusterNode remoteNode,
List<DeploymentUnit> units,
String jobClassName,
- Object... args
+ T arg
) {
- return executeRemotely(ExecutionOptions.DEFAULT, remoteNode, units, jobClassName, args);
+ return executeRemotely(ExecutionOptions.DEFAULT, remoteNode, units, jobClassName, arg);
}
/**
@@ -115,17 +116,17 @@ public interface ComputeComponent extends IgniteComponent {
* @param options Job execution options.
* @param units Deployment units which will be loaded for execution.
* @param jobClassName Name of the job class.
- * @param args Job args.
+ * @param arg Job args.
* @param <R> Job result type.
* @return Job execution object.
*/
- <R> JobExecution<R> executeRemotelyWithFailover(
+ <T, R> JobExecution<R> executeRemotelyWithFailover(
ClusterNode remoteNode,
NextWorkerSelector nextWorkerSelector,
List<DeploymentUnit> units,
String jobClassName,
ExecutionOptions options,
- Object... args
+ T arg
);
/**
@@ -134,15 +135,15 @@ public interface ComputeComponent extends IgniteComponent {
* @param jobSubmitter Function which submits a job with specified parameters for the execution.
* @param units Deployment units which will be loaded for execution.
* @param taskClassName Name of the task class.
- * @param args Task args.
+ * @param arg Task args.
* @param <R> Task result type.
* @return Task execution object.
*/
- <R> TaskExecution<R> executeTask(
- JobSubmitter jobSubmitter,
+ <I, M, T, R> TaskExecution<R> executeTask(
+ JobSubmitter<M, T> jobSubmitter,
List<DeploymentUnit> units,
String taskClassName,
- Object... args
+ I arg
);
/**
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeComponentImpl.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeComponentImpl.java
index f4dc3bd5d7..46f061f62b 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeComponentImpl.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeComponentImpl.java
@@ -116,11 +116,11 @@ public class ComputeComponentImpl implements ComputeComponent {
/** {@inheritDoc} */
@Override
- public <R> JobExecution<R> executeLocally(
+ public <I, R> JobExecution<R> executeLocally(
ExecutionOptions options,
List<DeploymentUnit> units,
String jobClassName,
- Object... args
+ I arg
) {
if (!busyLock.enterBusy()) {
return new DelegatingJobExecution<>(
@@ -132,7 +132,7 @@ public class ComputeComponentImpl implements ComputeComponent {
CompletableFuture<JobExecutionInternal<R>> future =
mapClassLoaderExceptions(jobContextManager.acquireClassLoader(units), jobClassName)
.thenApply(context -> {
- JobExecutionInternal<R> execution = execJob(context, options, jobClassName, args);
+ JobExecutionInternal<R> execution = execJob(context, options, jobClassName, arg);
execution.resultAsync().whenComplete((result, e) -> context.close());
inFlightFutures.registerFuture(execution.resultAsync());
return execution;
@@ -149,11 +149,11 @@ public class ComputeComponentImpl implements ComputeComponent {
}
@Override
- public <R> TaskExecution<R> executeTask(
- JobSubmitter jobSubmitter,
+ public <I, M, T, R> TaskExecution<R> executeTask(
+ JobSubmitter<M, T> jobSubmitter,
List<DeploymentUnit> units,
String taskClassName,
- Object... args
+ I input
) {
if (!busyLock.enterBusy()) {
return new DelegatingTaskExecution<>(
@@ -162,10 +162,10 @@ public class ComputeComponentImpl implements ComputeComponent {
}
try {
- CompletableFuture<TaskExecutionInternal<R>> taskFuture =
+ CompletableFuture<TaskExecutionInternal<I, M, T, R>> taskFuture =
mapClassLoaderExceptions(jobContextManager.acquireClassLoader(units), taskClassName)
.thenApply(context -> {
- TaskExecutionInternal<R> execution = execTask(context, jobSubmitter, taskClassName, args);
+ TaskExecutionInternal<I, M, T, R> execution = execTask(context, jobSubmitter, taskClassName, input);
execution.resultAsync().whenComplete((r, e) -> context.close());
inFlightFutures.registerFuture(execution.resultAsync());
return execution;
@@ -173,7 +173,7 @@ public class ComputeComponentImpl implements ComputeComponent {
inFlightFutures.registerFuture(taskFuture);
- DelegatingTaskExecution<R> result = new DelegatingTaskExecution<>(taskFuture);
+ DelegatingTaskExecution<I, M, T, R> result = new DelegatingTaskExecution<>(taskFuture);
result.idAsync().thenAccept(jobId -> executionManager.addExecution(jobId, new TaskToJobExecutionWrapper<>(result)));
return result;
} finally {
@@ -183,12 +183,12 @@ public class ComputeComponentImpl implements ComputeComponent {
/** {@inheritDoc} */
@Override
- public <R> JobExecution<R> executeRemotely(
+ public <T, R> JobExecution<R> executeRemotely(
ExecutionOptions options,
ClusterNode remoteNode,
List<DeploymentUnit> units,
String jobClassName,
- Object... args
+ T arg
) {
if (!busyLock.enterBusy()) {
return new DelegatingJobExecution<>(
@@ -197,7 +197,7 @@ public class ComputeComponentImpl implements ComputeComponent {
}
try {
- CompletableFuture<UUID> jobIdFuture = messaging.remoteExecuteRequestAsync(options, remoteNode, units, jobClassName, args);
+ CompletableFuture<UUID> jobIdFuture = messaging.remoteExecuteRequestAsync(options, remoteNode, units, jobClassName, arg);
CompletableFuture<R> resultFuture = jobIdFuture.thenCompose(jobId -> messaging.remoteJobResultRequestAsync(remoteNode, jobId));
inFlightFutures.registerFuture(jobIdFuture);
@@ -212,18 +212,18 @@ public class ComputeComponentImpl implements ComputeComponent {
}
@Override
- public <R> JobExecution<R> executeRemotelyWithFailover(
+ public <T, R> JobExecution<R> executeRemotelyWithFailover(
ClusterNode remoteNode,
NextWorkerSelector nextWorkerSelector,
List<DeploymentUnit> units,
String jobClassName,
ExecutionOptions options,
- Object... args
+ T arg
) {
JobExecution<R> result = new ComputeJobFailover<R>(
this, logicalTopologyService, topologyService,
remoteNode, nextWorkerSelector, failoverExecutor, units,
- jobClassName, options, args
+ jobClassName, options, arg
).failSafeExecute();
result.idAsync().thenAccept(jobId -> executionManager.addExecution(jobId, result));
@@ -293,7 +293,8 @@ public class ComputeComponentImpl implements ComputeComponent {
return nullCompletedFuture();
}
- private <R> JobExecutionInternal<R> execJob(JobContext context, ExecutionOptions options, String jobClassName, Object... args) {
+
+ private <T, R> JobExecutionInternal<R> execJob(JobContext context, ExecutionOptions options, String jobClassName, Object args) {
try {
return executor.executeJob(options, jobClass(context.classLoader(), jobClassName), context.classLoader(), args);
} catch (Throwable e) {
@@ -302,14 +303,14 @@ public class ComputeComponentImpl implements ComputeComponent {
}
}
- private <R> TaskExecutionInternal<R> execTask(
+ private <I, M, T, R> TaskExecutionInternal<I, M, T, R> execTask(
JobContext context,
- JobSubmitter jobSubmitter,
+ JobSubmitter<M, T> jobSubmitter,
String taskClassName,
- Object... args
+ I input
) {
try {
- return executor.executeTask(jobSubmitter, taskClass(context.classLoader(), taskClassName), args);
+ return executor.executeTask(jobSubmitter, taskClass(context.classLoader(), taskClassName), input);
} catch (Throwable e) {
context.close();
throw e;
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeJobFailover.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeJobFailover.java
index 3cba4da38b..7246401cac 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeJobFailover.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeJobFailover.java
@@ -42,9 +42,9 @@ import org.apache.ignite.network.ClusterNode;
* then you should create an instance of this class with workerNode = node1, failoverCandidates = [node2, node3] as arguments and call
* {@link #failSafeExecute()}.
*
- * @param <T> the type of the result of the job.
+ * @param <R> the type of the result of the job.
*/
-class ComputeJobFailover<T> {
+class ComputeJobFailover<R> {
private static final IgniteLogger LOG = Loggers.forClass(ComputeJobFailover.class);
/**
@@ -82,7 +82,7 @@ class ComputeJobFailover<T> {
/**
* Context of the called job. Captures deployment units, jobClassName and arguments.
*/
- private final RemoteExecutionContext<T> jobContext;
+ private final RemoteExecutionContext<?, R> jobContext;
/**
* Creates a per-job instance.
@@ -108,7 +108,7 @@ class ComputeJobFailover<T> {
List<DeploymentUnit> units,
String jobClassName,
ExecutionOptions executionOptions,
- Object... args
+ Object args
) {
this.computeComponent = computeComponent;
this.runningWorkerNode = new AtomicReference<>(workerNode);
@@ -124,8 +124,8 @@ class ComputeJobFailover<T> {
*
* @return JobExecution with the result of the job and the status of the job.
*/
- JobExecution<T> failSafeExecute() {
- JobExecution<T> jobExecution = launchJobOn(runningWorkerNode.get());
+ JobExecution<R> failSafeExecute() {
+ JobExecution<R> jobExecution = launchJobOn(runningWorkerNode.get());
jobContext.initJobExecution(new FailSafeJobExecution<>(jobExecution));
LogicalTopologyEventListener nodeLeftEventListener = new OnNodeLeft();
@@ -135,13 +135,14 @@ class ComputeJobFailover<T> {
return jobContext.failSafeJobExecution();
}
- private JobExecution<T> launchJobOn(ClusterNode runningWorkerNode) {
+ private JobExecution<R> launchJobOn(ClusterNode runningWorkerNode) {
if (runningWorkerNode.equals(topologyService.localMember())) {
- return computeComponent.executeLocally(jobContext.executionOptions(), jobContext.units(), jobContext.jobClassName(),
- jobContext.args());
+ return computeComponent.executeLocally(
+ jobContext.executionOptions(), jobContext.units(), jobContext.jobClassName(), jobContext.arg()
+ );
} else {
return computeComponent.executeRemotely(
- jobContext.executionOptions(), runningWorkerNode, jobContext.units(), jobContext.jobClassName(), jobContext.args()
+ jobContext.executionOptions(), runningWorkerNode, jobContext.units(), jobContext.jobClassName(), jobContext.arg()
);
}
}
@@ -180,7 +181,7 @@ class ComputeJobFailover<T> {
LOG.info("Restarting the job {} on node {}.", jobContext.jobClassName(), nextWorker.name());
runningWorkerNode.set(nextWorker);
- JobExecution<T> jobExecution = launchJobOn(runningWorkerNode.get());
+ JobExecution<R> jobExecution = launchJobOn(runningWorkerNode.get());
jobContext.updateJobExecution(jobExecution);
});
}
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeUtils.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeUtils.java
index b50dbd4089..226e9f82e2 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeUtils.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/ComputeUtils.java
@@ -61,7 +61,7 @@ public class ComputeUtils {
* @param <R> Compute job return type.
* @return Compute job instance.
*/
- public static <R> ComputeJob<R> instantiateJob(Class<? extends ComputeJob<R>> computeJobClass) {
+ public static <T, R> ComputeJob<T, R> instantiateJob(Class<? extends ComputeJob<T, R>> computeJobClass) {
if (!(ComputeJob.class.isAssignableFrom(computeJobClass))) {
throw new ComputeException(
CLASS_INITIALIZATION_ERR,
@@ -70,7 +70,7 @@ public class ComputeUtils {
}
try {
- Constructor<? extends ComputeJob<R>> constructor = computeJobClass.getDeclaredConstructor();
+ Constructor<? extends ComputeJob<T, R>> constructor = computeJobClass.getDeclaredConstructor();
if (!constructor.canAccess(null)) {
constructor.setAccessible(true);
@@ -90,9 +90,9 @@ public class ComputeUtils {
* @param <R> Compute job return type.
* @return Compute job class.
*/
- public static <R> Class<ComputeJob<R>> jobClass(ClassLoader jobClassLoader, String jobClassName) {
+ public static <T, R> Class<ComputeJob<T, R>> jobClass(ClassLoader jobClassLoader, String jobClassName) {
try {
- return (Class<ComputeJob<R>>) Class.forName(jobClassName, true, jobClassLoader);
+ return (Class<ComputeJob<T, R>>) Class.forName(jobClassName, true, jobClassLoader);
} catch (ClassNotFoundException e) {
throw new ComputeException(CLASS_INITIALIZATION_ERR, "Cannot load job class by name '" + jobClassName + "'", e);
}
@@ -105,7 +105,7 @@ public class ComputeUtils {
* @param <R> Map reduce task return type.
* @return Map reduce task instance.
*/
- public static <R> MapReduceTask<R> instantiateTask(Class<? extends MapReduceTask<R>> taskClass) {
+ public static <I, M, T, R> MapReduceTask<I, M, T, R> instantiateTask(Class<? extends MapReduceTask<I, M, T, R>> taskClass) {
if (!(MapReduceTask.class.isAssignableFrom(taskClass))) {
throw new ComputeException(
CLASS_INITIALIZATION_ERR,
@@ -114,7 +114,7 @@ public class ComputeUtils {
}
try {
- Constructor<? extends MapReduceTask<R>> constructor = taskClass.getDeclaredConstructor();
+ Constructor<? extends MapReduceTask<I, M, T, R>> constructor = taskClass.getDeclaredConstructor();
if (!constructor.canAccess(null)) {
constructor.setAccessible(true);
@@ -134,9 +134,9 @@ public class ComputeUtils {
* @param <R> Map reduce task return type.
* @return Map reduce task class.
*/
- public static <R> Class<MapReduceTask<R>> taskClass(ClassLoader taskClassLoader, String taskClassName) {
+ public static <I, M, T, R> Class<MapReduceTask<I, M, T, R>> taskClass(ClassLoader taskClassLoader, String taskClassName) {
try {
- return (Class<MapReduceTask<R>>) Class.forName(taskClassName, true, taskClassLoader);
+ return (Class<MapReduceTask<I, M, T, R>>) Class.forName(taskClassName, true, taskClassLoader);
} catch (ClassNotFoundException e) {
throw new ComputeException(CLASS_INITIALIZATION_ERR, "Cannot load task class by name '" + taskClassName + "'", e);
}
@@ -150,7 +150,7 @@ public class ComputeUtils {
* @param <R> Receiver return type.
* @return Receiver instance.
*/
- public static <T, R> DataStreamerReceiver<T, R> instantiateReceiver(Class<? extends DataStreamerReceiver<T, R>> recvClass) {
+ public static <T, R, A> DataStreamerReceiver<T, R, A> instantiateReceiver(Class<? extends DataStreamerReceiver<T, R, A>> recvClass) {
if (!(DataStreamerReceiver.class.isAssignableFrom(recvClass))) {
throw new ComputeException(
CLASS_INITIALIZATION_ERR,
@@ -159,7 +159,7 @@ public class ComputeUtils {
}
try {
- Constructor<? extends DataStreamerReceiver<T, R>> constructor = recvClass.getDeclaredConstructor();
+ Constructor<? extends DataStreamerReceiver<T, R, A>> constructor = recvClass.getDeclaredConstructor();
if (!constructor.canAccess(null)) {
constructor.setAccessible(true);
@@ -179,9 +179,9 @@ public class ComputeUtils {
* @param <R> Return type.
* @return Receiver class.
*/
- public static <T, R> Class<DataStreamerReceiver<T, R>> receiverClass(ClassLoader classLoader, String className) {
+ public static <T, R, A> Class<DataStreamerReceiver<T, R, A>> receiverClass(ClassLoader classLoader, String className) {
try {
- return (Class<DataStreamerReceiver<T, R>>) Class.forName(className, true, classLoader);
+ return (Class<DataStreamerReceiver<T, R, A>>) Class.forName(className, true, classLoader);
} catch (ClassNotFoundException e) {
throw new ComputeException(CLASS_INITIALIZATION_ERR, "Cannot load receiver class by name '" + className + "'", e);
}
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/IgniteComputeImpl.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/IgniteComputeImpl.java
index ca28742e80..200e8525e6 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/IgniteComputeImpl.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/IgniteComputeImpl.java
@@ -64,6 +64,7 @@ import org.apache.ignite.internal.util.ExceptionUtils;
import org.apache.ignite.lang.ErrorGroups.Compute;
import org.apache.ignite.lang.TableNotFoundException;
import org.apache.ignite.lang.util.IgniteNameUtils;
+import org.apache.ignite.marshaling.Marshaler;
import org.apache.ignite.network.ClusterNode;
import org.apache.ignite.table.Tuple;
import org.apache.ignite.table.mapper.Mapper;
@@ -98,14 +99,28 @@ public class IgniteComputeImpl implements IgniteComputeInternal {
}
@Override
- public <R> JobExecution<R> submit(JobTarget target, JobDescriptor descriptor, Object... args) {
+ public <T, R> JobExecution<R> submit(JobTarget target, JobDescriptor<T, R> descriptor, T args) {
Objects.requireNonNull(target);
Objects.requireNonNull(descriptor);
+ Marshaler<T, byte[]> argumentMarshaler = descriptor.argumentMarshaler();
+
if (target instanceof AnyNodeJobTarget) {
Set<ClusterNode> nodes = ((AnyNodeJobTarget) target).nodes();
- return executeAsyncWithFailover(nodes, descriptor.units(), descriptor.jobClassName(), descriptor.options(), args);
+ if (nodes.size() == 1) {
+ ClusterNode node = nodes.iterator().next();
+ if (node.id().equals(topologyService.localMember().id())) {
+ return executeAsyncWithFailover(
+ nodes, descriptor.units(), descriptor.jobClassName(), descriptor.options(), args
+ );
+ }
+ }
+
+ return executeAsyncWithFailover(
+ nodes, descriptor.units(), descriptor.jobClassName(), descriptor.options(),
+ argumentMarshaler == null ? args : argumentMarshaler.marshal(args)
+ );
}
if (target instanceof ColocatedJobTarget) {
@@ -124,7 +139,7 @@ public class IgniteComputeImpl implements IgniteComputeInternal {
descriptor.units(),
descriptor.jobClassName(),
descriptor.options(),
- args
+ argumentMarshaler == null ? args : argumentMarshaler.marshal(args)
)));
} else {
@@ -135,7 +150,7 @@ public class IgniteComputeImpl implements IgniteComputeInternal {
descriptor.units(),
descriptor.jobClassName(),
descriptor.options(),
- args));
+ argumentMarshaler == null ? args : argumentMarshaler.marshal(args)));
}
return new JobExecutionFutureWrapper<>(jobFut);
@@ -145,7 +160,7 @@ public class IgniteComputeImpl implements IgniteComputeInternal {
}
@Override
- public <R> R execute(JobTarget target, JobDescriptor descriptor, Object... args) {
+ public <T, R> R execute(JobTarget target, JobDescriptor<T, R> descriptor, T args) {
return sync(executeAsync(target, descriptor, args));
}
@@ -155,7 +170,7 @@ public class IgniteComputeImpl implements IgniteComputeInternal {
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object... args
+ Object args
) {
Set<ClusterNode> candidates = new HashSet<>();
for (ClusterNode node : nodes) {
@@ -195,19 +210,19 @@ public class IgniteComputeImpl implements IgniteComputeInternal {
return iterator.next();
}
- private <R> JobExecution<R> executeOnOneNodeWithFailover(
+ private <T, R> JobExecution<R> executeOnOneNodeWithFailover(
ClusterNode targetNode,
NextWorkerSelector nextWorkerSelector,
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions jobExecutionOptions,
- Object[] args
+ T payload
) {
ExecutionOptions options = ExecutionOptions.from(jobExecutionOptions);
if (isLocal(targetNode)) {
- return computeComponent.executeLocally(options, units, jobClassName, args);
+ return computeComponent.executeLocally(options, units, jobClassName, payload);
} else {
- return computeComponent.executeRemotelyWithFailover(targetNode, nextWorkerSelector, units, jobClassName, options, args);
+ return computeComponent.executeRemotelyWithFailover(targetNode, nextWorkerSelector, units, jobClassName, options, payload);
}
}
@@ -239,12 +254,12 @@ public class IgniteComputeImpl implements IgniteComputeInternal {
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object[] args) {
+ Object arg) {
return primaryReplicaForPartitionByTupleKey(table, key)
.thenApply(primaryNode -> executeOnOneNodeWithFailover(
primaryNode,
new NextColocatedWorkerSelector<>(placementDriver, topologyService, clock, table, key),
- units, jobClassName, options, args
+ units, jobClassName, options, arg
));
}
@@ -286,14 +301,15 @@ public class IgniteComputeImpl implements IgniteComputeInternal {
}
@Override
- public <R> Map<ClusterNode, JobExecution<R>> submitBroadcast(
+ public <T, R> Map<ClusterNode, JobExecution<R>> submitBroadcast(
Set<ClusterNode> nodes,
- JobDescriptor descriptor,
- Object... args
+ JobDescriptor<T, R> descriptor,
+ T args
) {
Objects.requireNonNull(nodes);
Objects.requireNonNull(descriptor);
+ Marshaler<T, byte[]> argumentMarshaler = descriptor.argumentMarshaler();
return nodes.stream()
.collect(toUnmodifiableMap(identity(),
// No failover nodes for broadcast. We use failover here in order to complete futures with exceptions
@@ -303,12 +319,13 @@ public class IgniteComputeImpl implements IgniteComputeInternal {
return new FailedExecution<>(new NodeNotFoundException(Set.of(node.name())));
}
return new JobExecutionWrapper<>(executeOnOneNodeWithFailover(node, CompletableFutures::nullCompletedFuture,
- descriptor.units(), descriptor.jobClassName(), descriptor.options(), args));
+ descriptor.units(), descriptor.jobClassName(), descriptor.options(),
+ argumentMarshaler == null ? args : argumentMarshaler.marshal(args)));
}));
}
@Override
- public <R> TaskExecution<R> submitMapReduce(List<DeploymentUnit> units, String taskClassName, Object... args) {
+ public <T, R> TaskExecution<R> submitMapReduce(List<DeploymentUnit> units, String taskClassName, T args) {
Objects.requireNonNull(units);
Objects.requireNonNull(taskClassName);
@@ -316,12 +333,12 @@ public class IgniteComputeImpl implements IgniteComputeInternal {
}
@Override
- public <R> R executeMapReduce(List<DeploymentUnit> units, String taskClassName, Object... args) {
+ public <T, R> R executeMapReduce(List<DeploymentUnit> units, String taskClassName, T args) {
return sync(executeMapReduceAsync(units, taskClassName, args));
}
- private JobExecution<Object> submitJob(MapReduceJob runner) {
- return submit(JobTarget.anyNode(runner.nodes()), runner.jobDescriptor(), runner.args());
+ private <M, T> JobExecution<T> submitJob(MapReduceJob<M, T> runner) {
+ return submit(JobTarget.anyNode(runner.nodes()), runner.jobDescriptor(), runner.arg());
}
@Override
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/IgniteComputeInternal.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/IgniteComputeInternal.java
index 449d57d07f..d2273c6acc 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/IgniteComputeInternal.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/IgniteComputeInternal.java
@@ -46,7 +46,7 @@ public interface IgniteComputeInternal extends IgniteCompute {
* @param units Deployment units. Can be empty.
* @param jobClassName Name of the job class to execute.
* @param options Job execution options.
- * @param args Arguments of the job.
+ * @param payload Arguments of the job.
* @return CompletableFuture Job result.
*/
<R> JobExecution<R> executeAsyncWithFailover(
@@ -54,7 +54,7 @@ public interface IgniteComputeInternal extends IgniteCompute {
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object... args
+ Object payload
);
/**
@@ -66,7 +66,7 @@ public interface IgniteComputeInternal extends IgniteCompute {
* @param units Deployment units. Can be empty.
* @param jobClassName Name of the job class to execute.
* @param options job execution options (priority, max retries).
- * @param args Arguments of the job.
+ * @param payload Arguments of the job.
* @param <R> Job result type.
* @return Job execution object.
*/
@@ -76,7 +76,7 @@ public interface IgniteComputeInternal extends IgniteCompute {
List<DeploymentUnit> units,
String jobClassName,
JobExecutionOptions options,
- Object[] args);
+ Object payload);
/**
* Wraps the given future into a job execution object.
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/JobStarter.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/JobStarter.java
index f96fbdfbee..941a4ad263 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/JobStarter.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/JobStarter.java
@@ -39,6 +39,6 @@ public interface JobStarter {
ExecutionOptions options,
List<DeploymentUnit> units,
String jobClassName,
- Object... args
+ Object args
);
}
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/RemoteExecutionContext.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/RemoteExecutionContext.java
index ff89760437..4aefcfc303 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/RemoteExecutionContext.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/RemoteExecutionContext.java
@@ -26,9 +26,10 @@ import org.apache.ignite.deployment.DeploymentUnit;
* Captures the context of a remote job execution. Also provides methods to access the job execution object
* that is returned to the user. The access is thread safe.
*
- * @param <T> type of the result of the job.
+ * @param <T> type of the input of the job.
+ * @param <R> type of the result of the job.
*/
-class RemoteExecutionContext<T> {
+class RemoteExecutionContext<T, R> {
private final ExecutionOptions executionOptions;
@@ -36,15 +37,15 @@ class RemoteExecutionContext<T> {
private final String jobClassName;
- private final Object[] args;
+ private final T arg;
- private final AtomicReference<FailSafeJobExecution<T>> jobExecution;
+ private final AtomicReference<FailSafeJobExecution<R>> jobExecution;
- RemoteExecutionContext(List<DeploymentUnit> units, String jobClassName, ExecutionOptions executionOptions, Object[] args) {
+ RemoteExecutionContext(List<DeploymentUnit> units, String jobClassName, ExecutionOptions executionOptions, T arg) {
this.executionOptions = executionOptions;
this.units = units;
this.jobClassName = jobClassName;
- this.args = args;
+ this.arg = arg;
this.jobExecution = new AtomicReference<>(null);
}
@@ -53,7 +54,7 @@ class RemoteExecutionContext<T> {
*
* @param jobExecution the instance of job execution that should be returned to the client.
*/
- void initJobExecution(FailSafeJobExecution<T> jobExecution) {
+ void initJobExecution(FailSafeJobExecution<R> jobExecution) {
if (!this.jobExecution.compareAndSet(null, jobExecution)) {
throw new IllegalStateException("Job execution is already initialized.");
}
@@ -64,8 +65,8 @@ class RemoteExecutionContext<T> {
*
* @return fail-safe job execution object.
*/
- FailSafeJobExecution<T> failSafeJobExecution() {
- FailSafeJobExecution<T> jobExecution = this.jobExecution.get();
+ FailSafeJobExecution<R> failSafeJobExecution() {
+ FailSafeJobExecution<R> jobExecution = this.jobExecution.get();
if (jobExecution == null) {
throw new IllegalStateException("Job execution is not initialized. Call initJobExecution() first.");
}
@@ -73,14 +74,13 @@ class RemoteExecutionContext<T> {
return jobExecution;
}
-
/**
* Updates the state of the job execution object but does not change the link to the object.
* The context holds exactly one link that is returned to the user and mutates its internal state only.
*
* @param jobExecution the new job execution object (supposed to be a restarted job but in another worker node).
*/
- void updateJobExecution(JobExecution<T> jobExecution) {
+ void updateJobExecution(JobExecution<R> jobExecution) {
failSafeJobExecution().updateJobExecution(jobExecution);
}
@@ -96,7 +96,7 @@ class RemoteExecutionContext<T> {
return jobClassName;
}
- Object[] args() {
- return args;
+ T arg() {
+ return arg;
}
}
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/executor/ComputeExecutor.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/executor/ComputeExecutor.java
index 8fc006dc90..9588ccaa60 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/executor/ComputeExecutor.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/executor/ComputeExecutor.java
@@ -28,13 +28,17 @@ import org.apache.ignite.internal.compute.task.TaskExecutionInternal;
* Executor of Compute jobs.
*/
public interface ComputeExecutor {
- <R> JobExecutionInternal<R> executeJob(
+ <T, R> JobExecutionInternal<R> executeJob(
ExecutionOptions options,
- Class<? extends ComputeJob<R>> jobClass,
+ Class<? extends ComputeJob<T, R>> jobClass,
JobClassLoader classLoader,
- Object... args);
+ T input);
- <R> TaskExecutionInternal<R> executeTask(JobSubmitter jobSubmitter, Class<? extends MapReduceTask<R>> taskClass, Object... args);
+ <I, M, T, R> TaskExecutionInternal<I, M, T, R> executeTask(
+ JobSubmitter<M, T> jobSubmitter,
+ Class<? extends MapReduceTask<I, M, T, R>> taskClass,
+ I input
+ );
void start();
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/executor/ComputeExecutorImpl.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/executor/ComputeExecutorImpl.java
index 2656536e6e..667f679985 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/executor/ComputeExecutorImpl.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/executor/ComputeExecutorImpl.java
@@ -40,6 +40,8 @@ import org.apache.ignite.internal.compute.task.TaskExecutionInternal;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.thread.IgniteThreadFactory;
+import org.apache.ignite.marshaling.Marshaler;
+import org.jetbrains.annotations.Nullable;
/**
* Base implementation of {@link ComputeExecutor}.
@@ -73,19 +75,21 @@ public class ComputeExecutorImpl implements ComputeExecutor {
}
@Override
- public <R> JobExecutionInternal<R> executeJob(
+ public <T, R> JobExecutionInternal<R> executeJob(
ExecutionOptions options,
- Class<? extends ComputeJob<R>> jobClass,
+ Class<? extends ComputeJob<T, R>> jobClass,
JobClassLoader classLoader,
- Object[] args
+ T input
) {
assert executorService != null;
AtomicBoolean isInterrupted = new AtomicBoolean();
JobExecutionContext context = new JobExecutionContextImpl(ignite, isInterrupted, classLoader);
+ ComputeJob<T, R> jobInstance = ComputeUtils.instantiateJob(jobClass);
+ Marshaler<T, byte[]> marshaller = jobInstance.inputMarshaler();
QueueExecution<R> execution = executorService.submit(
- () -> ComputeUtils.instantiateJob(jobClass).executeAsync(context, args),
+ () -> jobInstance.executeAsync(context, unmarshallOrNotIfNull(marshaller, input)),
options.priority(),
options.maxRetries()
);
@@ -93,18 +97,30 @@ public class ComputeExecutorImpl implements ComputeExecutor {
return new JobExecutionInternal<>(execution, isInterrupted);
}
+ private static <T> @Nullable T unmarshallOrNotIfNull(@Nullable Marshaler<T, byte[]> marshaller, Object input) {
+ if (marshaller == null) {
+ return (T) input;
+ }
+
+ if (input instanceof byte[]) {
+ return marshaller.unmarshal((byte[]) input);
+ }
+
+ return (T) input;
+ }
+
@Override
- public <R> TaskExecutionInternal<R> executeTask(
- JobSubmitter jobSubmitter,
- Class<? extends MapReduceTask<R>> taskClass,
- Object... args
+ public <I, M, T, R> TaskExecutionInternal<I, M, T, R> executeTask(
+ JobSubmitter<M, T> jobSubmitter,
+ Class<? extends MapReduceTask<I, M, T, R>> taskClass,
+ I input
) {
assert executorService != null;
AtomicBoolean isCancelled = new AtomicBoolean();
TaskExecutionContext context = new TaskExecutionContextImpl(ignite, isCancelled);
- return new TaskExecutionInternal<>(executorService, jobSubmitter, taskClass, context, isCancelled, args);
+ return new TaskExecutionInternal<>(executorService, jobSubmitter, taskClass, context, isCancelled, input);
}
@Override
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/message/ExecuteRequest.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/message/ExecuteRequest.java
index d30832be53..e82dcfcdb7 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/message/ExecuteRequest.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/message/ExecuteRequest.java
@@ -60,5 +60,6 @@ public interface ExecuteRequest extends NetworkMessage {
* @return arguments
*/
@Marshallable
- Object @Nullable [] args();
+ @Nullable
+ Object input();
}
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/messaging/ComputeMessaging.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/messaging/ComputeMessaging.java
index 6f900a95c1..6093f966da 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/messaging/ComputeMessaging.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/messaging/ComputeMessaging.java
@@ -171,15 +171,15 @@ public class ComputeMessaging {
* @param remoteNode The job will be executed on this node.
* @param units Deployment units. Can be empty.
* @param jobClassName Name of the job class to execute.
- * @param args Arguments of the job.
+ * @param input Arguments of the job.
* @return Job id future that will be completed when the job is submitted on the remote node.
*/
- public CompletableFuture<UUID> remoteExecuteRequestAsync(
+ public <T> CompletableFuture<UUID> remoteExecuteRequestAsync(
ExecutionOptions options,
ClusterNode remoteNode,
List<DeploymentUnit> units,
String jobClassName,
- Object[] args
+ T input
) {
List<DeploymentUnitMsg> deploymentUnitMsgs = units.stream()
.map(ComputeUtils::toDeploymentUnitMsg)
@@ -189,7 +189,7 @@ public class ComputeMessaging {
.executeOptions(options)
.deploymentUnits(deploymentUnitMsgs)
.jobClassName(jobClassName)
- .args(args)
+ .input(input)
.build();
return messagingService.invoke(remoteNode, executeRequest, NETWORK_TIMEOUT_MILLIS)
@@ -199,7 +199,9 @@ public class ComputeMessaging {
private void processExecuteRequest(JobStarter starter, ExecuteRequest request, ClusterNode sender, long correlationId) {
List<DeploymentUnit> units = toDeploymentUnit(request.deploymentUnits());
- JobExecution<Object> execution = starter.start(request.executeOptions(), units, request.jobClassName(), request.args());
+ JobExecution<Object> execution = starter.start(
+ request.executeOptions(), units, request.jobClassName(), request.input()
+ );
execution.idAsync().whenComplete((jobId, err) -> sendExecuteResponse(jobId, err, sender, correlationId));
}
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/DelegatingTaskExecution.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/DelegatingTaskExecution.java
index 076aa66d39..fc2c67ad10 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/DelegatingTaskExecution.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/DelegatingTaskExecution.java
@@ -29,10 +29,10 @@ import org.jetbrains.annotations.Nullable;
*
* @param <R> Result type.
*/
-public class DelegatingTaskExecution<R> implements TaskExecution<R> {
- private final CompletableFuture<TaskExecutionInternal<R>> delegate;
+public class DelegatingTaskExecution<I, M, T, R> implements TaskExecution<R> {
+ private final CompletableFuture<TaskExecutionInternal<I, M, T, R>> delegate;
- public DelegatingTaskExecution(CompletableFuture<TaskExecutionInternal<R>> delegate) {
+ public DelegatingTaskExecution(CompletableFuture<TaskExecutionInternal<I, M, T, R>> delegate) {
this.delegate = delegate;
}
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/JobSubmitter.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/JobSubmitter.java
index 5f5c98829f..df5350664e 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/JobSubmitter.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/JobSubmitter.java
@@ -24,11 +24,11 @@ import org.apache.ignite.compute.task.MapReduceJob;
* Compute job submitter.
*/
@FunctionalInterface
-public interface JobSubmitter {
+public interface JobSubmitter<T, R> {
/**
* Submits compute job for an execution.
*
* @param computeJobRunner Computer job start parameters.
*/
- JobExecution<Object> submit(MapReduceJob computeJobRunner);
+ JobExecution<R> submit(MapReduceJob<T, R> computeJobRunner);
}
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/TaskExecutionInternal.java b/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/TaskExecutionInternal.java
index 0f3ebe7bc8..5ce5ae124e 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/TaskExecutionInternal.java
+++ b/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/TaskExecutionInternal.java
@@ -58,7 +58,7 @@ import org.apache.ignite.internal.logger.Loggers;
import org.jetbrains.annotations.Nullable;
/**
- * Internal map reduce task execution object. Runs the {@link MapReduceTask#splitAsync(TaskExecutionContext, Object...)} method of the task
+ * Internal map reduce task execution object. Runs the {@link MapReduceTask#splitAsync(TaskExecutionContext, Object)} method of the task
* as a compute job, then submits the resulting list of jobs. Waits for completion of all compute jobs, then submits the
* {@link MapReduceTask#reduceAsync(TaskExecutionContext, Map)} method as a compute job. The result of the task is the result of the split
* method.
@@ -66,14 +66,14 @@ import org.jetbrains.annotations.Nullable;
* @param <R> Task result type.
*/
@SuppressWarnings("unchecked")
-public class TaskExecutionInternal<R> implements TaskExecution<R> {
+public class TaskExecutionInternal<I, M, T, R> implements TaskExecution<R> {
private static final IgniteLogger LOG = Loggers.forClass(TaskExecutionInternal.class);
- private final QueueExecution<SplitResult<R>> splitExecution;
+ private final QueueExecution<SplitResult<I, M, T, R>> splitExecution;
- private final CompletableFuture<List<JobExecution<Object>>> executionsFuture;
+ private final CompletableFuture<List<JobExecution<T>>> executionsFuture;
- private final CompletableFuture<Map<UUID, Object>> resultsFuture;
+ private final CompletableFuture<Map<UUID, T>> resultsFuture;
private final CompletableFuture<QueueExecution<R>> reduceExecutionFuture;
@@ -89,31 +89,32 @@ public class TaskExecutionInternal<R> implements TaskExecution<R> {
* @param taskClass Map reduce task class.
* @param context Task execution context.
* @param isCancelled Flag which is passed to the execution context so that the task can check it for cancellation request.
- * @param args Task arguments.
+ * @param arg Task argument.
*/
public TaskExecutionInternal(
PriorityQueueExecutor executorService,
JobSubmitter jobSubmitter,
- Class<? extends MapReduceTask<R>> taskClass,
+ Class<? extends MapReduceTask<I, M, T, R>> taskClass,
TaskExecutionContext context,
AtomicBoolean isCancelled,
- Object... args
+ I arg
) {
this.isCancelled = isCancelled;
LOG.debug("Executing task {}", taskClass.getName());
splitExecution = executorService.submit(
() -> {
- MapReduceTask<R> task = instantiateTask(taskClass);
+ MapReduceTask<I, M, T, R> task = instantiateTask(taskClass);
- return task.splitAsync(context, args)
+ return task.splitAsync(context, arg)
.thenApply(jobs -> new SplitResult<>(task, jobs));
},
+
Integer.MAX_VALUE,
0
);
executionsFuture = splitExecution.resultAsync().thenApply(splitResult -> {
- List<MapReduceJob> runners = splitResult.runners();
+ List<MapReduceJob<M, T>> runners = splitResult.runners();
LOG.debug("Submitting {} jobs for {}", runners.size(), taskClass.getName());
return submit(runners, jobSubmitter);
});
@@ -124,7 +125,7 @@ public class TaskExecutionInternal<R> implements TaskExecution<R> {
LOG.debug("Running reduce job for {}", taskClass.getName());
// This future is already finished
- MapReduceTask<R> task = splitExecution.resultAsync().thenApply(SplitResult::task).join();
+ MapReduceTask<I, M, T, R> task = splitExecution.resultAsync().thenApply(SplitResult::task).join();
return executorService.submit(
() -> task.reduceAsync(context, results),
@@ -271,8 +272,8 @@ public class TaskExecutionInternal<R> implements TaskExecution<R> {
}
- private static CompletableFuture<Map<UUID, Object>> resultsAsync(List<JobExecution<Object>> executions) {
- CompletableFuture<?>[] resultFutures = executions.stream()
+ private static <T> CompletableFuture<Map<UUID, T>> resultsAsync(List<JobExecution<T>> executions) {
+ CompletableFuture<T>[] resultFutures = executions.stream()
.map(JobExecution::resultAsync)
.toArray(CompletableFuture[]::new);
@@ -281,7 +282,7 @@ public class TaskExecutionInternal<R> implements TaskExecution<R> {
.toArray(CompletableFuture[]::new);
return allOf(concat(resultFutures, idFutures)).thenApply(unused -> {
- Map<UUID, Object> results = new HashMap<>();
+ Map<UUID, T> results = new HashMap<>();
for (int i = 0; i < resultFutures.length; i++) {
results.put(idFutures[i].join(), resultFutures[i].join());
@@ -291,27 +292,27 @@ public class TaskExecutionInternal<R> implements TaskExecution<R> {
});
}
- private static <R> List<JobExecution<Object>> submit(List<MapReduceJob> runners, JobSubmitter jobSubmitter) {
+ private static <M, T> List<JobExecution<T>> submit(List<MapReduceJob<M, T>> runners, JobSubmitter<M, T> jobSubmitter) {
return runners.stream()
.map(jobSubmitter::submit)
.collect(toList());
}
- private static class SplitResult<R> {
- private final MapReduceTask<R> task;
+ private static class SplitResult<I, M, T, R> {
+ private final MapReduceTask<I, M, T, R> task;
- private final List<MapReduceJob> runners;
+ private final List<MapReduceJob<M, T>> runners;
- private SplitResult(MapReduceTask<R> task, List<MapReduceJob> runners) {
+ private SplitResult(MapReduceTask<I, M, T, R> task, List<MapReduceJob<M, T>> runners) {
this.task = task;
this.runners = runners;
}
- private List<MapReduceJob> runners() {
+ private List<MapReduceJob<M, T>> runners() {
return runners;
}
- private MapReduceTask<R> task() {
+ private MapReduceTask<I, M, T, R> task() {
return task;
}
}
diff --git a/modules/compute/src/test/java/org/apache/ignite/internal/compute/ComputeComponentImplTest.java b/modules/compute/src/test/java/org/apache/ignite/internal/compute/ComputeComponentImplTest.java
index 5c69c07041..661a59d030 100644
--- a/modules/compute/src/test/java/org/apache/ignite/internal/compute/ComputeComponentImplTest.java
+++ b/modules/compute/src/test/java/org/apache/ignite/internal/compute/ComputeComponentImplTest.java
@@ -183,7 +183,7 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
@Test
void executesLocally() {
- JobExecution<String> execution = computeComponent.executeLocally(List.of(), SimpleJob.class.getName(), "a", 42);
+ JobExecution<String> execution = computeComponent.executeLocally(List.of(), SimpleJob.class.getName(), "");
assertThat(execution.resultAsync(), willBe("jobResponse"));
assertThat(execution.stateAsync(), willBe(jobStateWithStatus(COMPLETED)));
@@ -195,7 +195,7 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
@Test
void getsStateAndCancelsLocally() {
- JobExecution<String> execution = computeComponent.executeLocally(List.of(), LongJob.class.getName());
+ JobExecution<String> execution = computeComponent.executeLocally(List.of(), LongJob.class.getName(), null);
await().until(execution::stateAsync, willBe(jobStateWithStatus(EXECUTING)));
@@ -208,10 +208,10 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
@Test
void stateCancelAndChangePriorityTriesLocalNodeFirst() {
- JobExecution<String> runningExecution = computeComponent.executeLocally(List.of(), LongJob.class.getName());
+ JobExecution<String> runningExecution = computeComponent.executeLocally(List.of(), LongJob.class.getName(), null);
await().until(runningExecution::stateAsync, willBe(jobStateWithStatus(EXECUTING)));
- JobExecution<String> queuedExecution = computeComponent.executeLocally(List.of(), LongJob.class.getName());
+ JobExecution<String> queuedExecution = computeComponent.executeLocally(List.of(), LongJob.class.getName(), null);
await().until(queuedExecution::stateAsync, willBe(jobStateWithStatus(QUEUED)));
UUID jobId = queuedExecution.idAsync().join();
@@ -249,7 +249,9 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
respondWithJobStateResponseWhenJobStateRequestIsSent(jobId, COMPLETED);
respondWithJobCancelResponseWhenJobCancelRequestIsSent(jobId, false);
- JobExecution<String> execution = computeComponent.executeRemotely(remoteNode, List.of(), SimpleJob.class.getName(), "a", 42);
+ JobExecution<String> execution = computeComponent.executeRemotely(
+ remoteNode, List.of(), SimpleJob.class.getName(), "a"
+ );
assertThat(execution.resultAsync(), willBe("remoteResponse"));
// Verify that second invocation of resultAsync will not result in the network communication (i.e. the result is cached locally)
@@ -258,7 +260,7 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
assertThat(execution.stateAsync(), willBe(jobStateWithStatus(COMPLETED)));
assertThat(execution.cancelAsync(), willBe(false));
- assertThatExecuteRequestWasSent(SimpleJob.class.getName(), "a", 42);
+ assertThatExecuteRequestWasSent(SimpleJob.class.getName(), "a");
assertThatJobResultRequestWasSent(jobId);
assertThatJobStateRequestWasSent(jobId);
assertThatJobCancelRequestWasSent(jobId);
@@ -272,13 +274,13 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
respondWithJobStateResponseWhenJobStateRequestIsSent(jobId, EXECUTING);
respondWithJobCancelResponseWhenJobCancelRequestIsSent(jobId, true);
- JobExecution<String> execution = computeComponent.executeRemotely(remoteNode, List.of(), LongJob.class.getName());
+ JobExecution<String> execution = computeComponent.executeRemotely(remoteNode, List.of(), LongJob.class.getName(), null);
assertThat(execution.stateAsync(), willBe(jobStateWithStatus(EXECUTING)));
assertThat(execution.resultAsync(), willBe("remoteResponse"));
assertThat(execution.cancelAsync(), willBe(true));
- assertThatExecuteRequestWasSent(LongJob.class.getName());
+ assertThatExecuteRequestWasSent(LongJob.class.getName(), null);
assertThatJobResultRequestWasSent(jobId);
assertThatJobStateRequestWasSent(jobId);
assertThatJobCancelRequestWasSent(jobId);
@@ -290,7 +292,7 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
respondWithExecuteResponseWhenExecuteRequestIsSent(jobId);
respondWithJobChangePriorityResponseWhenJobChangePriorityRequestIsSent(jobId);
- JobExecution<String> execution = computeComponent.executeRemotely(remoteNode, List.of(), LongJob.class.getName());
+ JobExecution<String> execution = computeComponent.executeRemotely(remoteNode, List.of(), LongJob.class.getName(), null);
assertThat(execution.changePriorityAsync(1), willBe(true));
@@ -369,11 +371,11 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
return false;
}
- private void assertThatExecuteRequestWasSent(String jobClassName, Object... args) {
+ private void assertThatExecuteRequestWasSent(String jobClassName, String args) {
ExecuteRequest capturedRequest = invokeAndCaptureRequest(ExecuteRequest.class);
assertThat(capturedRequest.jobClassName(), is(jobClassName));
- assertThat(capturedRequest.args(), is(equalTo(args)));
+ assertThat(capturedRequest.input(), is(equalTo(args)));
}
private void assertThatJobResultRequestWasSent(UUID jobId) {
@@ -415,7 +417,7 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
() -> executeRemotely(FailingJob.class.getName()).get()
);
- assertThatExecuteRequestWasSent(FailingJob.class.getName());
+ assertThatExecuteRequestWasSent(FailingJob.class.getName(), null);
assertThat(ex.getCause(), is(instanceOf(JobException.class)));
assertThat(ex.getCause().getMessage(), is("Oops"));
@@ -428,7 +430,7 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
.executeOptions(DEFAULT)
.deploymentUnits(List.of())
.jobClassName(SimpleJob.class.getName())
- .args(new Object[]{"a", 42})
+ .input("")
.build();
ExecuteResponse executeResponse = sendRequestAndCaptureResponse(executeRequest, testNode, 123L);
@@ -495,7 +497,7 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
.executeOptions(DEFAULT)
.deploymentUnits(List.of())
.jobClassName(SimpleJob.class.getName())
- .args(new Object[]{"a", 42})
+ .input(new Object[]{"a", 42})
.build();
ExecuteResponse response = sendRequestAndCaptureResponse(request, testNode, 123L);
@@ -623,7 +625,7 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
.when(jobContextManager).acquireClassLoader(units);
assertThat(
- executeLocally(units, "com.example.Maim"),
+ executeLocally(units, "com.example.Maim", null),
willThrow(ClassNotFoundException.class)
);
}
@@ -641,7 +643,7 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
.when(jobContextManager).acquireClassLoader(units);
assertThat(
- executeLocally(units, "com.example.Maim"),
+ executeLocally(units, "com.example.Maim", null),
willThrow(ClassNotFoundException.class)
);
}
@@ -670,33 +672,43 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
return responseCaptor.getValue();
}
- private CompletableFuture<String> executeLocally(String jobClassName, Object... args) {
+ private CompletableFuture<String> executeLocally(String jobClassName, String args) {
return executeLocally(List.of(), jobClassName, args);
}
- private CompletableFuture<String> executeLocally(List<DeploymentUnit> units, String jobClassName, Object... args) {
- return computeComponent.<String>executeLocally(units, jobClassName, args).resultAsync();
+ private CompletableFuture<String> executeLocally(String jobClassName) {
+ return executeLocally(jobClassName, null);
+ }
+
+ private CompletableFuture<String> executeLocally(List<DeploymentUnit> units, String jobClassName, String args) {
+ return computeComponent.<String, String>executeLocally(units, jobClassName, args).resultAsync();
}
private CompletableFuture<String> executeRemotely(
String jobClassName,
- Object... args
+ String args
+ ) {
+ return computeComponent.<String, String>executeRemotely(remoteNode, List.of(), jobClassName, args).resultAsync();
+ }
+
+ private CompletableFuture<String> executeRemotely(
+ String jobClassName
) {
- return computeComponent.<String>executeRemotely(remoteNode, List.of(), jobClassName, args).resultAsync();
+ return executeRemotely(jobClassName, null);
}
- private static class SimpleJob implements ComputeJob<String> {
+ private static class SimpleJob implements ComputeJob<String, String> {
/** {@inheritDoc} */
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, String args) {
return completedFuture("jobResponse");
}
}
- private static class FailingJob implements ComputeJob<String> {
+ private static class FailingJob implements ComputeJob<String, String> {
/** {@inheritDoc} */
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, String args) {
throw new JobException("Oops", new Exception());
}
}
@@ -707,18 +719,18 @@ class ComputeComponentImplTest extends BaseIgniteAbstractTest {
}
}
- private static class GetThreadNameJob implements ComputeJob<String> {
+ private static class GetThreadNameJob implements ComputeJob<String, String> {
/** {@inheritDoc} */
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, String args) {
return completedFuture(Thread.currentThread().getName());
}
}
- private static class LongJob implements ComputeJob<String> {
+ private static class LongJob implements ComputeJob<Void, String> {
/** {@inheritDoc} */
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Void args) {
try {
Thread.sleep(1_000_000);
} catch (InterruptedException e) {
diff --git a/modules/compute/src/test/java/org/apache/ignite/internal/compute/IgniteComputeImplTest.java b/modules/compute/src/test/java/org/apache/ignite/internal/compute/IgniteComputeImplTest.java
index 2c26d48559..adb05fbbe9 100644
--- a/modules/compute/src/test/java/org/apache/ignite/internal/compute/IgniteComputeImplTest.java
+++ b/modules/compute/src/test/java/org/apache/ignite/internal/compute/IgniteComputeImplTest.java
@@ -24,7 +24,6 @@ import static org.apache.ignite.internal.util.CompletableFutures.trueCompletedFu
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.aMapWithSize;
import static org.hamcrest.Matchers.contains;
-import static org.mockito.AdditionalMatchers.aryEq;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -114,11 +113,11 @@ class IgniteComputeImplTest extends BaseIgniteAbstractTest {
compute.executeAsync(
JobTarget.node(localNode),
JobDescriptor.builder(JOB_CLASS_NAME).units(testDeploymentUnits).build(),
- "a", 42),
+ "a"),
willBe("jobResponse")
);
- verify(computeComponent).executeLocally(ExecutionOptions.DEFAULT, testDeploymentUnits, JOB_CLASS_NAME, "a", 42);
+ verify(computeComponent).executeLocally(ExecutionOptions.DEFAULT, testDeploymentUnits, JOB_CLASS_NAME, "a");
}
@Test
@@ -129,7 +128,7 @@ class IgniteComputeImplTest extends BaseIgniteAbstractTest {
compute.executeAsync(
JobTarget.node(remoteNode),
JobDescriptor.builder(JOB_CLASS_NAME).units(testDeploymentUnits).build(),
- "a", 42),
+ "a"),
willBe("remoteResponse")
);
@@ -146,11 +145,11 @@ class IgniteComputeImplTest extends BaseIgniteAbstractTest {
compute.executeAsync(
JobTarget.node(localNode),
JobDescriptor.builder(JOB_CLASS_NAME).units(testDeploymentUnits).options(options).build(),
- "a", 42),
+ "a"),
willBe("jobResponse")
);
- verify(computeComponent).executeLocally(expectedOptions, testDeploymentUnits, JOB_CLASS_NAME, "a", 42);
+ verify(computeComponent).executeLocally(expectedOptions, testDeploymentUnits, JOB_CLASS_NAME, "a");
}
@Test
@@ -164,7 +163,7 @@ class IgniteComputeImplTest extends BaseIgniteAbstractTest {
compute.executeAsync(
JobTarget.node(remoteNode),
JobDescriptor.builder(JOB_CLASS_NAME).units(testDeploymentUnits).options(options).build(),
- "a", 42),
+ "a"),
willBe("remoteResponse")
);
@@ -180,7 +179,7 @@ class IgniteComputeImplTest extends BaseIgniteAbstractTest {
compute.executeAsync(
JobTarget.colocated("test", Tuple.create(Map.of("k", 1))),
JobDescriptor.builder(JOB_CLASS_NAME).units(testDeploymentUnits).build(),
- "a", 42),
+ "a"),
willBe("remoteResponse")
);
}
@@ -194,7 +193,7 @@ class IgniteComputeImplTest extends BaseIgniteAbstractTest {
compute.executeAsync(
JobTarget.colocated("test", 1, Mapper.of(Integer.class)),
JobDescriptor.builder(JOB_CLASS_NAME).units(testDeploymentUnits).build(),
- "a", 42
+ "a"
),
willBe("remoteResponse")
);
@@ -206,7 +205,8 @@ class IgniteComputeImplTest extends BaseIgniteAbstractTest {
respondWhenExecutingSimpleJobRemotely(ExecutionOptions.DEFAULT);
CompletableFuture<Map<ClusterNode, String>> future = compute.executeBroadcastAsync(
- Set.of(localNode, remoteNode), JobDescriptor.builder(JOB_CLASS_NAME).units(testDeploymentUnits).build(), "a", 42
+ Set.of(localNode, remoteNode), JobDescriptor.<String, String>builder(JOB_CLASS_NAME).units(testDeploymentUnits).build(),
+ "a"
);
assertThat(future, willBe(aMapWithSize(2)));
@@ -224,19 +224,19 @@ class IgniteComputeImplTest extends BaseIgniteAbstractTest {
}
private void respondWhenExecutingSimpleJobLocally(ExecutionOptions executionOptions) {
- when(computeComponent.executeLocally(executionOptions, testDeploymentUnits, JOB_CLASS_NAME, "a", 42))
+ when(computeComponent.executeLocally(eq(executionOptions), eq(testDeploymentUnits), eq(JOB_CLASS_NAME), eq("a")))
.thenReturn(completedExecution("jobResponse"));
}
private void respondWhenExecutingSimpleJobRemotely(ExecutionOptions options) {
when(computeComponent.executeRemotelyWithFailover(
- eq(remoteNode), any(), eq(testDeploymentUnits), eq(JOB_CLASS_NAME), eq(options), aryEq(new Object[]{"a", 42})
+ eq(remoteNode), any(), eq(testDeploymentUnits), eq(JOB_CLASS_NAME), eq(options), eq("a")
)).thenReturn(completedExecution("remoteResponse"));
}
private void verifyExecuteRemotelyWithFailover(ExecutionOptions options) {
verify(computeComponent).executeRemotelyWithFailover(
- eq(remoteNode), any(), eq(testDeploymentUnits), eq(JOB_CLASS_NAME), eq(options), aryEq(new Object[]{"a", 42})
+ eq(remoteNode), any(), eq(testDeploymentUnits), eq(JOB_CLASS_NAME), eq(options), eq("a")
);
}
diff --git a/modules/compute/src/test/java/org/apache/ignite/internal/compute/executor/ComputeExecutorTest.java b/modules/compute/src/test/java/org/apache/ignite/internal/compute/executor/ComputeExecutorTest.java
index 0fc8b7959c..268caae640 100644
--- a/modules/compute/src/test/java/org/apache/ignite/internal/compute/executor/ComputeExecutorTest.java
+++ b/modules/compute/src/test/java/org/apache/ignite/internal/compute/executor/ComputeExecutorTest.java
@@ -72,9 +72,10 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
@Test
void threadInterruption() {
- JobExecutionInternal<Integer> execution = computeExecutor.executeJob(
+ JobExecutionInternal<?> execution = computeExecutor.executeJob(
ExecutionOptions.DEFAULT,
InterruptingJob.class,
+ null,
null
);
JobState executingState = await().until(execution::state, jobStateWithStatus(EXECUTING));
@@ -85,7 +86,7 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
);
}
- private static class InterruptingJob implements ComputeJob<Integer> {
+ private static class InterruptingJob implements ComputeJob<Object[], Integer> {
@Override
public CompletableFuture<Integer> executeAsync(JobExecutionContext context, Object... args) {
while (true) {
@@ -101,9 +102,10 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
@Test
void cooperativeCancellation() {
- JobExecutionInternal<Integer> execution = computeExecutor.executeJob(
+ JobExecutionInternal<?> execution = computeExecutor.executeJob(
ExecutionOptions.DEFAULT,
CancellingJob.class,
+ null,
null
);
JobState executingState = await().until(execution::state, jobStateWithStatus(EXECUTING));
@@ -114,7 +116,7 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
);
}
- private static class CancellingJob implements ComputeJob<Integer> {
+ private static class CancellingJob implements ComputeJob<Object[], Integer> {
@Override
public CompletableFuture<Integer> executeAsync(JobExecutionContext context, Object... args) {
while (true) {
@@ -136,11 +138,11 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
int maxRetries = 5;
- JobExecutionInternal<Integer> execution = computeExecutor.executeJob(
+ JobExecutionInternal<?> execution = computeExecutor.executeJob(
ExecutionOptions.builder().maxRetries(maxRetries).build(),
RetryJobFail.class,
null,
- runTimes
+ new Object[]{runTimes}
);
await().until(execution::state, jobStateWithStatus(FAILED));
@@ -148,7 +150,7 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
assertThat(runTimes.get(), is(maxRetries + 1));
}
- private static class RetryJobFail implements ComputeJob<Integer> {
+ private static class RetryJobFail implements ComputeJob<Object[], Integer> {
@Override
public CompletableFuture<Integer> executeAsync(JobExecutionContext context, Object... args) {
@@ -164,12 +166,14 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
int maxRetries = 5;
- JobExecutionInternal<Integer> execution = computeExecutor.executeJob(
+ JobExecutionInternal<?> execution = computeExecutor.executeJob(
ExecutionOptions.builder().maxRetries(maxRetries).build(),
RetryJobSuccess.class,
null,
- runTimes,
- maxRetries
+ new Object[]{
+ runTimes,
+ maxRetries
+ }
);
await().until(execution::state, jobStateWithStatus(COMPLETED));
@@ -177,7 +181,7 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
assertThat(runTimes.get(), is(maxRetries + 1));
}
- private static class RetryJobSuccess implements ComputeJob<Integer> {
+ private static class RetryJobSuccess implements ComputeJob<Object[], Integer> {
@Override
public CompletableFuture<Integer> executeAsync(JobExecutionContext context, Object... args) {
@@ -197,11 +201,11 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
int maxRetries = 5;
- JobExecutionInternal<Integer> execution = computeExecutor.executeJob(
+ JobExecutionInternal<?> execution = computeExecutor.executeJob(
ExecutionOptions.builder().maxRetries(maxRetries).build(),
JobSuccess.class,
null,
- runTimes
+ new Object[]{runTimes}
);
await().until(execution::state, jobStateWithStatus(COMPLETED));
@@ -210,7 +214,7 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
assertThat(runTimes.get(), is(1));
}
- private static class JobSuccess implements ComputeJob<Integer> {
+ private static class JobSuccess implements ComputeJob<Object[], Integer> {
@Override
public CompletableFuture<Integer> executeAsync(JobExecutionContext context, Object... args) {
@@ -222,9 +226,10 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
@Test
void cancelCompletedJob() {
- JobExecutionInternal<Integer> execution = computeExecutor.executeJob(
+ JobExecutionInternal<?> execution = computeExecutor.executeJob(
ExecutionOptions.DEFAULT,
SimpleJob.class,
+ null,
null
);
@@ -233,7 +238,7 @@ class ComputeExecutorTest extends BaseIgniteAbstractTest {
assertThat(execution.cancel(), is(false));
}
- private static class SimpleJob implements ComputeJob<Integer> {
+ private static class SimpleJob implements ComputeJob<Object[], Integer> {
@Override
public CompletableFuture<Integer> executeAsync(JobExecutionContext context, Object... args) {
return completedFuture(0);
diff --git a/modules/compute/src/test/java/org/apache/ignite/internal/compute/loader/JobClassLoaderFactoryTest.java b/modules/compute/src/test/java/org/apache/ignite/internal/compute/loader/JobClassLoaderFactoryTest.java
index 328ae1084f..a3b8a1a48b 100644
--- a/modules/compute/src/test/java/org/apache/ignite/internal/compute/loader/JobClassLoaderFactoryTest.java
+++ b/modules/compute/src/test/java/org/apache/ignite/internal/compute/loader/JobClassLoaderFactoryTest.java
@@ -66,14 +66,14 @@ class JobClassLoaderFactoryTest extends BaseIgniteAbstractTest {
JobClassLoader classLoader2 = jobClassLoaderFactory.createClassLoader(units2)) {
// then classes from the first unit are loaded from the first class loader
Class<?> clazz1 = classLoader1.loadClass(UNIT_JOB_CLASS_NAME);
- ComputeJob<Integer> job1 = (ComputeJob<Integer>) clazz1.getDeclaredConstructor().newInstance();
- CompletableFuture<Integer> result1 = job1.executeAsync(null);
+ ComputeJob<Void, Integer> job1 = (ComputeJob<Void, Integer>) clazz1.getDeclaredConstructor().newInstance();
+ CompletableFuture<Integer> result1 = job1.executeAsync(null, null);
assertThat(result1, willBe(1));
// and classes from the second unit are loaded from the second class loader
Class<?> clazz2 = classLoader2.loadClass(UNIT_JOB_CLASS_NAME);
- ComputeJob<String> job2 = (ComputeJob<String>) clazz2.getDeclaredConstructor().newInstance();
- CompletableFuture<String> result2 = job2.executeAsync(null);
+ ComputeJob<Void, String> job2 = (ComputeJob<Void, String>) clazz2.getDeclaredConstructor().newInstance();
+ CompletableFuture<String> result2 = job2.executeAsync(null, null);
assertThat(result2, willBe("Hello World!"));
}
}
@@ -92,8 +92,8 @@ class JobClassLoaderFactoryTest extends BaseIgniteAbstractTest {
assertNotNull(unitJobClass);
// and classes are loaded in the aplhabetical order
- ComputeJob<Integer> job1 = (ComputeJob<Integer>) unitJobClass.getDeclaredConstructor().newInstance();
- CompletableFuture<Integer> result1 = job1.executeAsync(null);
+ ComputeJob<Void, Integer> job1 = (ComputeJob<Void, Integer>) unitJobClass.getDeclaredConstructor().newInstance();
+ CompletableFuture<Integer> result1 = job1.executeAsync(null, null);
assertThat(result1, willBe(1));
Class<?> job1UtilityClass = classLoader.loadClass(JOB1_UTILITY_CLASS_NAME);
diff --git a/modules/compute/src/unit1/java/org/apache/ignite/internal/compute/UnitJob.java b/modules/compute/src/unit1/java/org/apache/ignite/internal/compute/UnitJob.java
index 2b5fe0d9ca..94e48b99a0 100644
--- a/modules/compute/src/unit1/java/org/apache/ignite/internal/compute/UnitJob.java
+++ b/modules/compute/src/unit1/java/org/apache/ignite/internal/compute/UnitJob.java
@@ -24,9 +24,9 @@ import org.apache.ignite.compute.ComputeJob;
import org.apache.ignite.compute.JobExecutionContext;
/** Compute job. */
-public class UnitJob implements ComputeJob<Integer> {
+public class UnitJob implements ComputeJob<Void, Integer> {
@Override
- public CompletableFuture<Integer> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<Integer> executeAsync(JobExecutionContext context, Void input) {
return completedFuture(1);
}
}
diff --git a/modules/compute/src/unit2/java/org/apache/ignite/internal/compute/UnitJob.java b/modules/compute/src/unit2/java/org/apache/ignite/internal/compute/UnitJob.java
index 631e225821..c7a9846bfd 100644
--- a/modules/compute/src/unit2/java/org/apache/ignite/internal/compute/UnitJob.java
+++ b/modules/compute/src/unit2/java/org/apache/ignite/internal/compute/UnitJob.java
@@ -24,9 +24,9 @@ import org.apache.ignite.compute.ComputeJob;
import org.apache.ignite.compute.JobExecutionContext;
/** Compute job. */
-public class UnitJob implements ComputeJob<String> {
+public class UnitJob implements ComputeJob<Void, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Void input) {
return completedFuture("Hello World!");
}
}
diff --git a/modules/platforms/cpp/ignite/client/compute/compute.cpp b/modules/platforms/cpp/ignite/client/compute/compute.cpp
index d8a5a1242c..21d9ac31e0 100644
--- a/modules/platforms/cpp/ignite/client/compute/compute.cpp
+++ b/modules/platforms/cpp/ignite/client/compute/compute.cpp
@@ -22,15 +22,15 @@
namespace ignite {
void compute::submit_async(const std::vector<cluster_node> &nodes, std::shared_ptr<job_descriptor> descriptor,
- const std::vector<primitive> &args, ignite_callback<job_execution> callback) {
+ const binary_object &arg, ignite_callback<job_execution> callback) {
detail::arg_check::container_non_empty(nodes, "Nodes container");
detail::arg_check::container_non_empty(descriptor->get_job_class_name(), "Job class name");
- m_impl->submit_to_nodes(nodes, descriptor, args, std::move(callback));
+ m_impl->submit_to_nodes(nodes, descriptor, arg, std::move(callback));
}
void compute::submit_broadcast_async(const std::set<cluster_node> &nodes, std::shared_ptr<job_descriptor> descriptor,
- const std::vector<primitive> &args,
+ const binary_object &arg,
ignite_callback<std::map<cluster_node, ignite_result<job_execution>>> callback) {
typedef std::map<cluster_node, ignite_result<job_execution>> result_type;
@@ -52,7 +52,7 @@ void compute::submit_broadcast_async(const std::set<cluster_node> &nodes, std::s
for (const auto &node : nodes) {
std::vector<cluster_node> candidates = {node};
- m_impl->submit_to_nodes(candidates, descriptor, args, [node, shared_res](auto &&res) {
+ m_impl->submit_to_nodes(candidates, descriptor, arg, [node, shared_res](auto &&res) {
auto &val = *shared_res;
std::lock_guard<std::mutex> lock(val.m_mutex);
@@ -65,14 +65,13 @@ void compute::submit_broadcast_async(const std::set<cluster_node> &nodes, std::s
}
void compute::submit_colocated_async(std::string_view table_name, const ignite_tuple &key,
- std::shared_ptr<job_descriptor> descriptor, const std::vector<primitive> &args,
- ignite_callback<job_execution> callback) {
+ std::shared_ptr<job_descriptor> descriptor, const binary_object &arg, ignite_callback<job_execution> callback) {
detail::arg_check::container_non_empty(table_name, "Table name");
detail::arg_check::tuple_non_empty(key, "Key tuple");
detail::arg_check::container_non_empty(descriptor->get_job_class_name(), "Job class name");
m_impl->submit_colocated_async(
- std::string(table_name), key, descriptor, args, std::move(callback));
+ std::string(table_name), key, descriptor, arg, std::move(callback));
}
} // namespace ignite
diff --git a/modules/platforms/cpp/ignite/client/compute/compute.h b/modules/platforms/cpp/ignite/client/compute/compute.h
index 4108d1cc44..1c62618183 100644
--- a/modules/platforms/cpp/ignite/client/compute/compute.h
+++ b/modules/platforms/cpp/ignite/client/compute/compute.h
@@ -24,6 +24,7 @@
#include "ignite/client/network/cluster_node.h"
#include "ignite/client/table/ignite_tuple.h"
#include "ignite/client/transaction/transaction.h"
+#include "ignite/common/binary_object.h"
#include "ignite/common/detail/config.h"
#include "ignite/common/ignite_result.h"
#include "ignite/common/primitive.h"
@@ -56,24 +57,24 @@ public:
*
* @param nodes Nodes to use for the job execution.
* @param descriptor Descriptor.
- * @param args Job arguments.
+ * @param arg Job argument.
* @param callback A callback called on operation completion with job execution result.
*/
IGNITE_API void submit_async(const std::vector<cluster_node> &nodes, std::shared_ptr<job_descriptor> descriptor,
- const std::vector<primitive> &args, ignite_callback<job_execution> callback);
+ const binary_object &arg, ignite_callback<job_execution> callback);
/**
* Submits for execution a compute job represented by the given class on one of the specified nodes.
*
* @param nodes Nodes to use for the job execution.
* @param descriptor Descriptor.
- * @param args Job arguments.
+ * @param arg Job argument.
* @return Job execution result.
*/
IGNITE_API job_execution submit(const std::vector<cluster_node> &nodes, std::shared_ptr<job_descriptor> descriptor,
- const std::vector<primitive> &args) {
+ const binary_object &arg) {
return sync<job_execution>([&](auto callback) mutable {
- submit_async(nodes, descriptor, args, std::move(callback));
+ submit_async(nodes, descriptor, arg, std::move(callback));
});
}
@@ -82,11 +83,11 @@ public:
*
* @param nodes Nodes to use for the job execution.
* @param descriptor Descriptor.
- * @param args Job arguments.
+ * @param arg Job argument.
* @param callback A callback called on operation completion with jobs execution result.
*/
IGNITE_API void submit_broadcast_async(const std::set<cluster_node> &nodes,
- std::shared_ptr<job_descriptor> descriptor, const std::vector<primitive> &args,
+ std::shared_ptr<job_descriptor> descriptor, const binary_object &arg,
ignite_callback<std::map<cluster_node, ignite_result<job_execution>>> callback);
/**
@@ -94,14 +95,14 @@ public:
*
* @param nodes Nodes to use for the job execution.
* @param descriptor Descriptor.
- * @param args Job arguments.
+ * @param arg Job argument.
* @return Job execution result.
*/
IGNITE_API std::map<cluster_node, ignite_result<job_execution>> submit_broadcast(
const std::set<cluster_node> &nodes, std::shared_ptr<job_descriptor> descriptor,
- const std::vector<primitive> &args) {
+ const binary_object &arg) {
return sync<std::map<cluster_node, ignite_result<job_execution>>>([&](auto callback) mutable {
- submit_broadcast_async(nodes, descriptor, args, std::move(callback));
+ submit_broadcast_async(nodes, descriptor, arg, std::move(callback));
});
}
@@ -111,11 +112,11 @@ public:
* @param table_name Name of the table to be used with @c key to determine target node.
* @param key Table key to be used to determine the target node for job execution.
* @param descriptor Descriptor.
- * @param args Job arguments.
+ * @param arg Job argument.
* @param callback A callback called on operation completion with job execution result.
*/
IGNITE_API void submit_colocated_async(std::string_view table_name, const ignite_tuple &key,
- std::shared_ptr<job_descriptor> descriptor, const std::vector<primitive> &args,
+ std::shared_ptr<job_descriptor> descriptor, const binary_object &arg,
ignite_callback<job_execution> callback);
/**
@@ -124,13 +125,13 @@ public:
* @param table_name Name of the table to be used with @c key to determine target node.
* @param key Table key to be used to determine the target node for job execution.
* @param descriptor Descriptor.
- * @param args Job arguments.
+ * @param arg Job argument.
* @return Job execution result.
*/
IGNITE_API job_execution submit_colocated(std::string_view table_name, const ignite_tuple &key,
- std::shared_ptr<job_descriptor> descriptor, const std::vector<primitive> &args) {
+ std::shared_ptr<job_descriptor> descriptor, const binary_object &arg) {
return sync<job_execution>([&](auto callback) mutable {
- submit_colocated_async(table_name, key, descriptor, args, std::move(callback));
+ submit_colocated_async(table_name, key, descriptor, arg, std::move(callback));
});
}
diff --git a/modules/platforms/cpp/ignite/client/compute/job_descriptor.h b/modules/platforms/cpp/ignite/client/compute/job_descriptor.h
index d895a18155..f483e45a39 100644
--- a/modules/platforms/cpp/ignite/client/compute/job_descriptor.h
+++ b/modules/platforms/cpp/ignite/client/compute/job_descriptor.h
@@ -21,6 +21,7 @@
#include "ignite/client/compute/job_execution_options.h"
#include <string>
+#include <utility>
#include <vector>
#include <memory>
@@ -62,13 +63,22 @@ public:
*/
class builder {
public:
+ /**
+ * Constructor.
+ *
+ * @param job_class_name Job class name.
+ */
+ explicit builder(std::string job_class_name) {
+ m_descriptor->m_job_class_name = std::move(job_class_name);
+ }
+
/**
* Set job class name.
*
* @param job_class_name Job class name.
*/
- builder& set_job_class_name(const std::string &job_class_name) {
- m_descriptor->m_job_class_name = job_class_name;
+ builder& job_class_name(std::string job_class_name) {
+ m_descriptor->m_job_class_name = std::move(job_class_name);
return *this;
}
@@ -77,7 +87,7 @@ public:
*
* @param units Deployment units to set.
*/
- builder& set_deployment_units(std::vector<deployment_unit> units) {
+ builder& deployment_units(std::vector<deployment_unit> units) {
m_descriptor->m_units = std::move(units);
return *this;
}
@@ -87,8 +97,8 @@ public:
*
* @param options Execution options.
*/
- builder& set_execution_options(const job_execution_options &options) {
- m_descriptor->m_options = options;
+ builder& execution_options(job_execution_options options) {
+ m_descriptor->m_options = std::move(options); // NOLINT(*-move-const-arg)
return *this;
}
diff --git a/modules/platforms/cpp/ignite/client/compute/job_execution.cpp b/modules/platforms/cpp/ignite/client/compute/job_execution.cpp
index 3d83e5efdb..0540544188 100644
--- a/modules/platforms/cpp/ignite/client/compute/job_execution.cpp
+++ b/modules/platforms/cpp/ignite/client/compute/job_execution.cpp
@@ -28,7 +28,7 @@ void job_execution::get_state_async(ignite_callback<std::optional<job_state>> ca
m_impl->get_state_async(std::move(callback));
}
-void job_execution::get_result_async(ignite_callback<std::optional<primitive>> callback) {
+void job_execution::get_result_async(ignite_callback<std::optional<binary_object>> callback) {
m_impl->get_result_async(std::move(callback));
}
diff --git a/modules/platforms/cpp/ignite/client/compute/job_execution.h b/modules/platforms/cpp/ignite/client/compute/job_execution.h
index 1159e05680..8ef30195fa 100644
--- a/modules/platforms/cpp/ignite/client/compute/job_execution.h
+++ b/modules/platforms/cpp/ignite/client/compute/job_execution.h
@@ -20,7 +20,7 @@
#include "ignite/client/compute/job_state.h"
#include "ignite/common/detail/config.h"
#include "ignite/common/ignite_result.h"
-#include "ignite/common/primitive.h"
+#include "ignite/common/binary_object.h"
#include "ignite/common/uuid.h"
#include <memory>
@@ -96,7 +96,7 @@ public:
* parallel.
* @param callback Callback to be called when the operation is complete. Called with the job execution result.
*/
- IGNITE_API void get_result_async(ignite_callback<std::optional<primitive>> callback);
+ IGNITE_API void get_result_async(ignite_callback<std::optional<binary_object>> callback);
/**
* Gets the job execution result.
@@ -105,8 +105,9 @@ public:
* multiple threads.
* @return The job execution result.
*/
- IGNITE_API std::optional<primitive> get_result() {
- return sync<std::optional<primitive>>([this](auto callback) mutable { get_result_async(std::move(callback)); });
+ IGNITE_API std::optional<binary_object> get_result() {
+ return sync<std::optional<binary_object>>(
+ [this](auto callback) mutable { get_result_async(std::move(callback)); });
}
/**
diff --git a/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.cpp b/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.cpp
index 52903bcd67..1de9bc3e4e 100644
--- a/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.cpp
+++ b/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.cpp
@@ -28,24 +28,15 @@ namespace ignite::detail {
* Write a collection of primitives as a binary tuple.
*
* @param writer Writer to use.
- * @param args Arguments.
+ * @param arg Argument.
*/
-void write_primitives_as_binary_tuple(protocol::writer &writer, const std::vector<primitive> &args) {
- auto args_num = std::int32_t(args.size());
-
- writer.write(args_num);
-
- binary_tuple_builder args_builder{args_num * 3};
+void write_object_as_binary_tuple(protocol::writer &writer, const binary_object &arg) {
+ binary_tuple_builder args_builder{3};
args_builder.start();
- for (const auto &arg : args) {
- protocol::claim_primitive_with_type(args_builder, arg);
- }
-
+ protocol::claim_primitive_with_type(args_builder, arg.get_primitive());
args_builder.layout();
- for (const auto &arg : args) {
- protocol::append_primitive_with_type(args_builder, arg);
- }
+ protocol::append_primitive_with_type(args_builder, arg.get_primitive());
auto args_data = args_builder.build();
writer.write_binary(args_data);
@@ -235,9 +226,9 @@ private:
};
void compute_impl::submit_to_nodes(const std::vector<cluster_node> &nodes, std::shared_ptr<job_descriptor> descriptor,
- const std::vector<primitive> &args, ignite_callback<job_execution> callback) {
+ const binary_object &arg, ignite_callback<job_execution> callback) {
- auto writer_func = [&nodes, &descriptor, args](protocol::writer &writer) {
+ auto writer_func = [&nodes, &descriptor, arg](protocol::writer &writer) {
auto nodes_num = std::int32_t(nodes.size());
writer.write(nodes_num);
for (const auto &node : nodes) {
@@ -249,7 +240,7 @@ void compute_impl::submit_to_nodes(const std::vector<cluster_node> &nodes, std::
writer.write(descriptor->get_execution_options().get_priority());
writer.write(descriptor->get_execution_options().get_max_retries());
- write_primitives_as_binary_tuple(writer, args);
+ write_object_as_binary_tuple(writer, arg);
};
auto handler = std::make_shared<response_handler_compute>(shared_from_this(), std::move(callback), false);
@@ -259,11 +250,11 @@ void compute_impl::submit_to_nodes(const std::vector<cluster_node> &nodes, std::
}
void compute_impl::submit_colocated_async(const std::string &table_name, const ignite_tuple &key,
- std::shared_ptr<job_descriptor> descriptor, const std::vector<primitive> &args,
+ std::shared_ptr<job_descriptor> descriptor, const binary_object &arg,
ignite_callback<job_execution> callback) {
auto self = shared_from_this();
auto conn = m_connection;
- auto on_table_get = [self, table_name, key, descriptor, args, conn, callback](auto &&res) mutable {
+ auto on_table_get = [self, table_name, key, descriptor, arg, conn, callback](auto &&res) mutable {
if (res.has_error()) {
callback({std::move(res.error())});
return;
@@ -276,8 +267,8 @@ void compute_impl::submit_colocated_async(const std::string &table_name, const i
auto table = table_impl::from_facade(*table_opt);
table->template with_proper_schema_async<job_execution>(
- callback, [self, table, key, descriptor, args, conn](const schema &sch, auto callback) mutable {
- auto writer_func = [&key, &descriptor, &sch, &table, &args](protocol::writer &writer) {
+ callback, [self, table, key, descriptor, arg, conn](const schema &sch, auto callback) mutable {
+ auto writer_func = [&key, &descriptor, &sch, &table, &arg](protocol::writer &writer) {
writer.write(table->get_id());
writer.write(sch.version);
write_tuple(writer, sch, key, true);
@@ -287,7 +278,7 @@ void compute_impl::submit_colocated_async(const std::string &table_name, const i
writer.write(descriptor->get_execution_options().get_priority());
writer.write(descriptor->get_execution_options().get_max_retries());
- write_primitives_as_binary_tuple(writer, args);
+ write_object_as_binary_tuple(writer, arg);
};
auto handler = std::make_shared<response_handler_compute>(self, std::move(callback), true);
diff --git a/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.h b/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.h
index 639450cd29..9df6736e33 100644
--- a/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.h
+++ b/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.h
@@ -25,6 +25,7 @@
#include "ignite/client/detail/table/tables_impl.h"
#include "ignite/client/network/cluster_node.h"
#include "ignite/client/table/ignite_tuple.h"
+#include "ignite/common/binary_object.h"
#include "ignite/common/ignite_result.h"
#include "ignite/common/primitive.h"
@@ -55,11 +56,11 @@ public:
*
* @param nodes Candidate node to use for the job execution.
* @param descriptor Descriptor.
- * @param args Job arguments.
+ * @param arg Job argument.
* @param callback A callback called on operation completion with job execution result.
*/
void submit_to_nodes(const std::vector<cluster_node> &nodes, std::shared_ptr<job_descriptor> descriptor,
- const std::vector<primitive> &args, ignite_callback<job_execution> callback);
+ const binary_object &arg, ignite_callback<job_execution> callback);
/**
* Submits a compute job represented by the given class for an execution on one of the nodes where the given key is
@@ -68,11 +69,11 @@ public:
* @param table_name Name of the table to be used with @c key to determine target node.
* @param key Table key to be used to determine the target node for job execution.
* @param descriptor Descriptor.
- * @param args Job arguments.
+ * @param arg Job argument.
* @param callback A callback called on operation completion with job execution result.
*/
void submit_colocated_async(const std::string &table_name, const ignite_tuple &key,
- std::shared_ptr<job_descriptor> descriptor, const std::vector<primitive> &args,
+ std::shared_ptr<job_descriptor> descriptor, const binary_object &arg,
ignite_callback<job_execution> callback);
/**
diff --git a/modules/platforms/cpp/ignite/client/detail/compute/job_execution_impl.cpp b/modules/platforms/cpp/ignite/client/detail/compute/job_execution_impl.cpp
index 3679984854..4de3d1a0c7 100644
--- a/modules/platforms/cpp/ignite/client/detail/compute/job_execution_impl.cpp
+++ b/modules/platforms/cpp/ignite/client/detail/compute/job_execution_impl.cpp
@@ -20,7 +20,7 @@
namespace ignite::detail {
-void job_execution_impl::get_result_async(ignite_callback<std::optional<primitive>> callback) {
+void job_execution_impl::get_result_async(ignite_callback<std::optional<binary_object>> callback) {
std::unique_lock<std::mutex> guard(m_mutex);
if (m_result) {
@@ -37,21 +37,26 @@ void job_execution_impl::get_result_async(ignite_callback<std::optional<primitiv
if (m_result_callback)
throw ignite_error("A callback for this result was already submitted");
- m_result_callback = std::make_shared<ignite_callback<std::optional<primitive>>>(std::move(callback));
+ m_result_callback = std::make_shared<ignite_callback<std::optional<binary_object>>>(std::move(callback));
}
}
void job_execution_impl::set_result(std::optional<primitive> result) {
+ std::optional<binary_object> obj;
+ if (result) {
+ obj = binary_object{std::move(*result)};
+ }
+
std::unique_lock<std::mutex> guard(m_mutex);
- m_result = result;
+ m_result = obj;
auto callback = std::move(m_result_callback);
m_result_callback.reset();
guard.unlock();
if (callback) {
- (*callback)({std::move(result)});
+ (*callback)({std::move(obj)});
}
}
diff --git a/modules/platforms/cpp/ignite/client/detail/compute/job_execution_impl.h b/modules/platforms/cpp/ignite/client/detail/compute/job_execution_impl.h
index 5701771371..7add7985cc 100644
--- a/modules/platforms/cpp/ignite/client/detail/compute/job_execution_impl.h
+++ b/modules/platforms/cpp/ignite/client/detail/compute/job_execution_impl.h
@@ -61,7 +61,7 @@ public:
* parallel.
* @param callback Callback to be called when the operation is complete. Called with the job execution result.
*/
- void get_result_async(ignite_callback<std::optional<primitive>> callback);
+ void get_result_async(ignite_callback<std::optional<binary_object>> callback);
/**
* Set result.
@@ -123,13 +123,13 @@ private:
std::optional<job_state> m_final_state;
/** Execution result. First optional to understand if the result is available. */
- std::optional<std::optional<primitive>> m_result;
+ std::optional<std::optional<binary_object>> m_result;
/** Error. */
std::optional<ignite_error> m_error;
/** Result callback. */
- std::shared_ptr<ignite_callback<std::optional<primitive>>> m_result_callback;
+ std::shared_ptr<ignite_callback<std::optional<binary_object>>> m_result_callback;
};
} // namespace ignite::detail
diff --git a/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/JobSubmitter.java b/modules/platforms/cpp/ignite/common/binary_object.h
similarity index 56%
copy from modules/compute/src/main/java/org/apache/ignite/internal/compute/task/JobSubmitter.java
copy to modules/platforms/cpp/ignite/common/binary_object.h
index 5f5c98829f..619638288e 100644
--- a/modules/compute/src/main/java/org/apache/ignite/internal/compute/task/JobSubmitter.java
+++ b/modules/platforms/cpp/ignite/common/binary_object.h
@@ -15,20 +15,39 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.compute.task;
+#pragma once
-import org.apache.ignite.compute.JobExecution;
-import org.apache.ignite.compute.task.MapReduceJob;
+#include "primitive.h"
+
+namespace ignite {
/**
- * Compute job submitter.
+ * Ignite binary_object type.
*/
-@FunctionalInterface
-public interface JobSubmitter {
+class binary_object {
+public:
+ // Default
+ binary_object() = default;
+
+ /**
+ * Primitive constructor.
+ *
+ * @param value Primitive type value.
+ */
+ binary_object(primitive value) // NOLINT(google-explicit-constructor)
+ : m_value(std::move(value)) {}
+
/**
- * Submits compute job for an execution.
+ * Get underlying primitive value.
*
- * @param computeJobRunner Computer job start parameters.
+ * @throw ignite_error If the packed value is not a primitive.
+ * @return Primitive value.
*/
- JobExecution<Object> submit(MapReduceJob computeJobRunner);
-}
+ primitive get_primitive() const { return m_value; }
+
+private:
+ /** Value. */
+ primitive m_value;
+};
+
+} // namespace ignite
diff --git a/modules/platforms/cpp/ignite/common/error_codes.h b/modules/platforms/cpp/ignite/common/error_codes.h
old mode 100755
new mode 100644
index 5dcd1fbaa5..03ee6f3e64
--- a/modules/platforms/cpp/ignite/common/error_codes.h
+++ b/modules/platforms/cpp/ignite/common/error_codes.h
@@ -51,7 +51,8 @@ enum class group : underlying_t {
PLACEMENTDRIVER = 0x12,
WORKERS = 0x13,
RECOVERY = 0x14,
- EMBEDDED = 0x15
+ EMBEDDED = 0x15,
+ MARSHALLING = 0x16
};
inline group get_group_by_error_code(const underlying_t code) {
@@ -219,7 +220,11 @@ enum class code : underlying_t {
CLUSTER_NOT_INITIALIZED = 0x150001,
CLUSTER_INIT_FAILED = 0x150002,
NODE_NOT_STARTED = 0x150003,
- NODE_START = 0x150004
+ NODE_START = 0x150004,
+
+ // Marshalling group. Group code: 22
+ COMMON = 0x160001,
+ UNSUPPORTED_OBJECT_TYPE = 0x160002
};
} // namespace error
diff --git a/modules/platforms/cpp/ignite/odbc/common_types.cpp b/modules/platforms/cpp/ignite/odbc/common_types.cpp
index 3f993e4efe..29e2265e53 100644
--- a/modules/platforms/cpp/ignite/odbc/common_types.cpp
+++ b/modules/platforms/cpp/ignite/odbc/common_types.cpp
@@ -311,6 +311,11 @@ sql_state error_code_to_sql_state(error::code code) {
case error::code::NODE_NOT_STARTED:
case error::code::NODE_START:
return sql_state::SHY000_GENERAL_ERROR;
+
+ // Marshalling group. Group code: 22
+ case error::code::COMMON:
+ case error::code::UNSUPPORTED_OBJECT_TYPE:
+ return sql_state::SHY000_GENERAL_ERROR;
}
return sql_state::SHY000_GENERAL_ERROR;
diff --git a/modules/platforms/cpp/tests/client-test/compute_test.cpp b/modules/platforms/cpp/tests/client-test/compute_test.cpp
index 8fe007cf18..78420c1081 100644
--- a/modules/platforms/cpp/tests/client-test/compute_test.cpp
+++ b/modules/platforms/cpp/tests/client-test/compute_test.cpp
@@ -71,11 +71,17 @@ protected:
template<typename T>
void check_argument(T value, const std::string &expected_str) {
auto cluster_nodes = m_client.get_cluster_nodes();
- auto execution = m_client.get_compute().submit(cluster_nodes, m_echo_job_desc, {value, expected_str});
+ auto execution = m_client.get_compute().submit(cluster_nodes, m_echo_job, {value});
auto result = execution.get_result();
ASSERT_TRUE(result.has_value());
- EXPECT_EQ(result.value().template get<T>(), value);
+ EXPECT_EQ(result.value().get_primitive().template get<T>(), value);
+
+ execution = m_client.get_compute().submit(cluster_nodes, m_to_string_job, {value});
+ result = execution.get_result();
+
+ ASSERT_TRUE(result.has_value());
+ EXPECT_EQ(result.value().get_primitive().template get<std::string>(), expected_str);
}
/**
@@ -92,20 +98,23 @@ protected:
/** Ignite client. */
ignite_client m_client;
- /** Node name job descriptor. */
- std::shared_ptr<job_descriptor> m_node_name_job_desc{job_descriptor::builder().set_job_class_name(NODE_NAME_JOB).build()};
+ /** Node name job. */
+ std::shared_ptr<job_descriptor> m_node_name_job{job_descriptor::builder(NODE_NAME_JOB).build()};
- /** Echo job descriptor. */
- std::shared_ptr<job_descriptor> m_echo_job_desc{job_descriptor::builder().set_job_class_name(ECHO_JOB).build()};
+ /** Echo job. */
+ std::shared_ptr<job_descriptor> m_echo_job{job_descriptor::builder(ECHO_JOB).build()};
- /** Concat job descriptor. */
- std::shared_ptr<job_descriptor> m_concat_job_desc{job_descriptor::builder().set_job_class_name(CONCAT_JOB).build()};
+ /** Concat job. */
+ std::shared_ptr<job_descriptor> m_concat_job{job_descriptor::builder(CONCAT_JOB).build()};
- /** Error job descriptor. */
- std::shared_ptr<job_descriptor> m_error_job_desc{job_descriptor::builder().set_job_class_name(ERROR_JOB).build()};
+ /** Error job. */
+ std::shared_ptr<job_descriptor> m_error_job{job_descriptor::builder(ERROR_JOB).build()};
- /** Sleep job descriptor. */
- std::shared_ptr<job_descriptor> m_sleep_job_desc{job_descriptor::builder().set_job_class_name(SLEEP_JOB).build()};
+ /** Sleep job. */
+ std::shared_ptr<job_descriptor> m_sleep_job{job_descriptor::builder(SLEEP_JOB).build()};
+
+ /** ToString job. */
+ std::shared_ptr<job_descriptor> m_to_string_job{job_descriptor::builder(TO_STRING_JOB).build()};
};
TEST_F(compute_test, get_cluster_nodes) {
@@ -131,16 +140,16 @@ TEST_F(compute_test, get_cluster_nodes) {
TEST_F(compute_test, execute_on_random_node) {
auto cluster_nodes = m_client.get_cluster_nodes();
- auto execution = m_client.get_compute().submit(cluster_nodes, m_node_name_job_desc, {});
+ auto execution = m_client.get_compute().submit(cluster_nodes, m_node_name_job, {});
auto result = execution.get_result();
ASSERT_TRUE(result.has_value());
- EXPECT_THAT(result.value().get<std::string>(), ::testing::StartsWith(PLATFORM_TEST_NODE_RUNNER));
+ EXPECT_THAT(result.value().get_primitive().get<std::string>(), ::testing::StartsWith(PLATFORM_TEST_NODE_RUNNER));
}
TEST_F(compute_test, execute_on_specific_node) {
- auto execution1 = m_client.get_compute().submit({get_node(0)}, m_node_name_job_desc, {"-", 11});
- auto execution2 = m_client.get_compute().submit({get_node(1)}, m_node_name_job_desc, {":", 22});
+ auto execution1 = m_client.get_compute().submit({get_node(0)}, m_node_name_job, {"-11"});
+ auto execution2 = m_client.get_compute().submit({get_node(1)}, m_node_name_job, {42});
auto res1 = execution1.get_result();
auto res2 = execution2.get_result();
@@ -148,40 +157,30 @@ TEST_F(compute_test, execute_on_specific_node) {
ASSERT_TRUE(res1.has_value());
ASSERT_TRUE(res2.has_value());
- EXPECT_EQ(res1.value().get<std::string>(), PLATFORM_TEST_NODE_RUNNER + "-_11");
- EXPECT_EQ(res2.value().get<std::string>(), PLATFORM_TEST_NODE_RUNNER + "_2:_22");
+ EXPECT_EQ(res1.value().get_primitive().get<std::string>(), PLATFORM_TEST_NODE_RUNNER + "-11");
+ EXPECT_EQ(res2.value().get_primitive().get<std::string>(), PLATFORM_TEST_NODE_RUNNER + "_242");
}
TEST_F(compute_test, execute_broadcast_one_node) {
- auto res = m_client.get_compute().submit_broadcast({get_node(1)}, m_node_name_job_desc, {"42"});
+ auto res = m_client.get_compute().submit_broadcast({get_node(1)}, m_node_name_job, {"42"});
ASSERT_EQ(res.size(), 1);
EXPECT_EQ(res.begin()->first, get_node(1));
ASSERT_TRUE(res.begin()->second.has_value());
- EXPECT_EQ(res.begin()->second.value().get_result(), PLATFORM_TEST_NODE_RUNNER + "_242");
+ EXPECT_EQ(res.begin()->second.value().get_result()->get_primitive(), PLATFORM_TEST_NODE_RUNNER + "_242");
}
TEST_F(compute_test, execute_broadcast_all_nodes) {
- auto res = m_client.get_compute().submit_broadcast(get_node_set(), m_node_name_job_desc, {"42"});
+ auto res = m_client.get_compute().submit_broadcast(get_node_set(), m_node_name_job, {"42"});
ASSERT_EQ(res.size(), 4);
- EXPECT_EQ(res[get_node(0)].value().get_result(), get_node(0).get_name() + "42");
- EXPECT_EQ(res[get_node(1)].value().get_result(), get_node(1).get_name() + "42");
- EXPECT_EQ(res[get_node(2)].value().get_result(), get_node(2).get_name() + "42");
- EXPECT_EQ(res[get_node(3)].value().get_result(), get_node(3).get_name() + "42");
-}
-
-TEST_F(compute_test, execute_with_args) {
- auto cluster_nodes = m_client.get_cluster_nodes();
-
- auto execution = m_client.get_compute().submit(cluster_nodes, m_concat_job_desc, {5.3, uuid(), "42", nullptr});
- auto result = execution.get_result();
-
- ASSERT_TRUE(result.has_value());
- EXPECT_EQ(result.value().get<std::string>(), "5.3_00000000-0000-0000-0000-000000000000_42_null");
+ EXPECT_EQ(res[get_node(0)].value().get_result()->get_primitive(), get_node(0).get_name() + "42");
+ EXPECT_EQ(res[get_node(1)].value().get_result()->get_primitive(), get_node(1).get_name() + "42");
+ EXPECT_EQ(res[get_node(2)].value().get_result()->get_primitive(), get_node(2).get_name() + "42");
+ EXPECT_EQ(res[get_node(3)].value().get_result()->get_primitive(), get_node(3).get_name() + "42");
}
TEST_F(compute_test, job_error_propagates_to_client) {
@@ -190,7 +189,7 @@ TEST_F(compute_test, job_error_propagates_to_client) {
EXPECT_THROW(
{
try {
- m_client.get_compute().submit(cluster_nodes, m_error_job_desc, {"unused"}).get_result();
+ m_client.get_compute().submit(cluster_nodes, m_error_job, {"unused"}).get_result();
} catch (const ignite_error &e) {
EXPECT_THAT(e.what_str(), testing::HasSubstr("Custom job error"));
// TODO https://issues.apache.org/jira/browse/IGNITE-19603
@@ -210,7 +209,7 @@ TEST_F(compute_test, unknown_node_execute_throws) {
EXPECT_THROW(
{
try {
- m_client.get_compute().submit({unknown_node}, m_echo_job_desc, {"unused"});
+ m_client.get_compute().submit({unknown_node}, m_echo_job, {"unused"});
} catch (const ignite_error &e) {
EXPECT_THAT(e.what_str(),
testing::HasSubstr("None of the specified nodes are present in the cluster: [random]"));
@@ -227,7 +226,7 @@ TEST_F(compute_test, DISABLED_unknown_node_broadcast_throws) {
EXPECT_THROW(
{
try {
- m_client.get_compute().submit_broadcast({unknown_node}, m_echo_job_desc, {"unused"});
+ m_client.get_compute().submit_broadcast({unknown_node}, m_echo_job, {"unused"});
} catch (const ignite_error &e) {
EXPECT_THAT(e.what_str(),
testing::HasSubstr("None of the specified nodes are present in the cluster: [random]"));
@@ -288,11 +287,11 @@ TEST_F(compute_test, submit_colocated) {
SCOPED_TRACE("key=" + std::to_string(var.first) + ", node=" + var.second);
auto key = get_tuple(var.first);
- auto execution = m_client.get_compute().submit_colocated(TABLE_1, key, m_node_name_job_desc, {});
+ auto execution = m_client.get_compute().submit_colocated(TABLE_1, key, m_node_name_job, {});
auto res_node_name = execution.get_result();
auto expected_node_name = PLATFORM_TEST_NODE_RUNNER + var.second;
- EXPECT_EQ(expected_node_name, res_node_name.value().get<std::string>());
+ EXPECT_EQ(expected_node_name, res_node_name.value().get_primitive().get<std::string>());
}
}
@@ -300,7 +299,7 @@ TEST_F(compute_test, execute_colocated_throws_when_table_does_not_exist) {
EXPECT_THROW(
{
try {
- (void) m_client.get_compute().submit_colocated("unknownTable", get_tuple(42), m_echo_job_desc, {});
+ (void) m_client.get_compute().submit_colocated("unknownTable", get_tuple(42), m_echo_job, {});
} catch (const ignite_error &e) {
EXPECT_STREQ("Table does not exist: 'unknownTable'", e.what());
throw;
@@ -313,7 +312,7 @@ TEST_F(compute_test, execute_colocated_throws_when_key_column_is_missing) {
EXPECT_THROW(
{
try {
- (void) m_client.get_compute().submit_colocated(TABLE_1, get_tuple("some"), m_echo_job_desc, {});
+ (void) m_client.get_compute().submit_colocated(TABLE_1, get_tuple("some"), m_echo_job, {});
} catch (const ignite_error &e) {
EXPECT_THAT(e.what_str(), ::testing::HasSubstr("Missed key column: KEY"));
throw;
@@ -326,7 +325,7 @@ TEST_F(compute_test, execute_colocated_throws_when_key_is_empty) {
EXPECT_THROW(
{
try {
- (void) m_client.get_compute().submit_colocated(TABLE_1, {}, m_echo_job_desc, {});
+ (void) m_client.get_compute().submit_colocated(TABLE_1, {}, m_echo_job, {});
} catch (const ignite_error &e) {
EXPECT_EQ("Key tuple can not be empty", e.what_str());
throw;
@@ -340,9 +339,8 @@ TEST_F(compute_test, unknown_unit) {
{
try {
auto cluster_nodes = m_client.get_cluster_nodes();
- auto job_desc = job_descriptor::builder()
- .set_job_class_name(NODE_NAME_JOB)
- .set_deployment_units({{"unknown"}})
+ auto job_desc = job_descriptor::builder(NODE_NAME_JOB)
+ .deployment_units({{"unknown"}})
.build();
(void) m_client.get_compute().submit(cluster_nodes, job_desc, {});
@@ -359,9 +357,8 @@ TEST_F(compute_test, execute_unknown_unit_and_version) {
{
try {
auto cluster_nodes = m_client.get_cluster_nodes();
- auto job_desc = job_descriptor::builder()
- .set_job_class_name(NODE_NAME_JOB)
- .set_deployment_units({{"unknown", "1.2.3"}})
+ auto job_desc = job_descriptor::builder(NODE_NAME_JOB)
+ .deployment_units({{"unknown", "1.2.3"}})
.build();
(void) m_client.get_compute().submit(cluster_nodes, job_desc, {});
@@ -378,9 +375,8 @@ TEST_F(compute_test, execute_colocated_unknown_unit_and_version) {
{
try {
auto comp = m_client.get_compute();
- auto job_desc = job_descriptor::builder()
- .set_job_class_name(NODE_NAME_JOB)
- .set_deployment_units({{"unknown", "1.2.3"}})
+ auto job_desc = job_descriptor::builder(NODE_NAME_JOB)
+ .deployment_units({{"unknown", "1.2.3"}})
.build();
(void) comp.submit_colocated(TABLE_1, get_tuple(1), job_desc, {});
@@ -393,9 +389,8 @@ TEST_F(compute_test, execute_colocated_unknown_unit_and_version) {
}
TEST_F(compute_test, broadcast_unknown_unit_and_version) {
- auto job_desc = job_descriptor::builder()
- .set_job_class_name(NODE_NAME_JOB)
- .set_deployment_units({{"unknown", "1.2.3"}})
+ auto job_desc = job_descriptor::builder(NODE_NAME_JOB)
+ .deployment_units({{"unknown", "1.2.3"}})
.build();
auto res = m_client.get_compute().submit_broadcast({get_node(1)}, job_desc, {});
@@ -411,9 +406,8 @@ TEST_F(compute_test, execute_empty_unit_name) {
EXPECT_THROW(
{
try {
- auto job_desc = job_descriptor::builder()
- .set_job_class_name(NODE_NAME_JOB)
- .set_deployment_units({{""}})
+ auto job_desc = job_descriptor::builder(NODE_NAME_JOB)
+ .deployment_units({{""}})
.build();
(void) m_client.get_compute().submit({get_node(1)}, job_desc, {});
@@ -429,9 +423,8 @@ TEST_F(compute_test, execute_empty_unit_version) {
EXPECT_THROW(
{
try {
- auto job_desc = job_descriptor::builder()
- .set_job_class_name(NODE_NAME_JOB)
- .set_deployment_units({{"some", ""}})
+ auto job_desc = job_descriptor::builder(NODE_NAME_JOB)
+ .deployment_units({{"some", ""}})
.build();
(void) m_client.get_compute().submit({get_node(1)}, job_desc, {});
@@ -447,9 +440,8 @@ TEST_F(compute_test, broadcast_empty_unit_name) {
EXPECT_THROW(
{
try {
- auto job_desc = job_descriptor::builder()
- .set_job_class_name(NODE_NAME_JOB)
- .set_deployment_units({{""}})
+ auto job_desc = job_descriptor::builder(NODE_NAME_JOB)
+ .deployment_units({{""}})
.build();
(void) m_client.get_compute().submit_broadcast({get_node(1)}, job_desc, {});
@@ -465,9 +457,8 @@ TEST_F(compute_test, broadcast_empty_unit_version) {
EXPECT_THROW(
{
try {
- auto job_desc = job_descriptor::builder()
- .set_job_class_name(NODE_NAME_JOB)
- .set_deployment_units({{"some", ""}})
+ auto job_desc = job_descriptor::builder(NODE_NAME_JOB)
+ .deployment_units({{"some", ""}})
.build();
(void) m_client.get_compute().submit_broadcast({get_node(1)}, job_desc, {});
@@ -483,9 +474,8 @@ TEST_F(compute_test, execute_colocated_empty_unit_name) {
EXPECT_THROW(
{
try {
- auto job_desc = job_descriptor::builder()
- .set_job_class_name(NODE_NAME_JOB)
- .set_deployment_units({{""}})
+ auto job_desc = job_descriptor::builder(NODE_NAME_JOB)
+ .deployment_units({{""}})
.build();
(void) m_client.get_compute().submit_colocated(TABLE_1, get_tuple(1), job_desc, {});
@@ -502,9 +492,8 @@ TEST_F(compute_test, execute_colocated_empty_unit_version) {
{
try {
auto comp = m_client.get_compute();
- auto job_desc = job_descriptor::builder()
- .set_job_class_name(NODE_NAME_JOB)
- .set_deployment_units({{"some", ""}})
+ auto job_desc = job_descriptor::builder(NODE_NAME_JOB)
+ .deployment_units({{"some", ""}})
.build();
comp.submit_colocated(TABLE_1, get_tuple(1), job_desc, {});
@@ -519,7 +508,7 @@ TEST_F(compute_test, execute_colocated_empty_unit_version) {
TEST_F(compute_test, job_execution_status_executing) {
const std::int32_t sleep_ms = 3000;
- auto execution = m_client.get_compute().submit({get_node(1)}, m_sleep_job_desc, {sleep_ms});
+ auto execution = m_client.get_compute().submit({get_node(1)}, m_sleep_job, {sleep_ms});
auto state = execution.get_state();
@@ -530,7 +519,7 @@ TEST_F(compute_test, job_execution_status_executing) {
TEST_F(compute_test, DISABLED_job_execution_status_completed) {
const std::int32_t sleep_ms = 1;
- auto execution = m_client.get_compute().submit({get_node(1)}, m_sleep_job_desc, {sleep_ms});
+ auto execution = m_client.get_compute().submit({get_node(1)}, m_sleep_job, {sleep_ms});
execution.get_result();
auto state = execution.get_state();
@@ -540,7 +529,7 @@ TEST_F(compute_test, DISABLED_job_execution_status_completed) {
}
TEST_F(compute_test, job_execution_status_failed) {
- auto execution = m_client.get_compute().submit({get_node(1)}, m_error_job_desc, {"unused"});
+ auto execution = m_client.get_compute().submit({get_node(1)}, m_error_job, {"unused"});
EXPECT_THROW(
{
@@ -562,7 +551,7 @@ TEST_F(compute_test, job_execution_status_failed) {
TEST_F(compute_test, job_execution_cancel) {
const std::int32_t sleep_ms = 5000;
- auto execution = m_client.get_compute().submit({get_node(1)}, m_sleep_job_desc, {sleep_ms});
+ auto execution = m_client.get_compute().submit({get_node(1)}, m_sleep_job, {sleep_ms});
execution.cancel();
auto state = execution.get_state();
@@ -574,7 +563,7 @@ TEST_F(compute_test, job_execution_cancel) {
TEST_F(compute_test, job_execution_change_priority) {
const std::int32_t sleep_ms = 5000;
- auto execution = m_client.get_compute().submit({get_node(1)}, m_sleep_job_desc, {sleep_ms});
+ auto execution = m_client.get_compute().submit({get_node(1)}, m_sleep_job, {sleep_ms});
auto res = execution.change_priority(123);
EXPECT_EQ(res, job_execution::operation_result::INVALID_STATE);
diff --git a/modules/platforms/cpp/tests/client-test/ignite_runner_suite.h b/modules/platforms/cpp/tests/client-test/ignite_runner_suite.h
index de50312392..63a1fbcae4 100644
--- a/modules/platforms/cpp/tests/client-test/ignite_runner_suite.h
+++ b/modules/platforms/cpp/tests/client-test/ignite_runner_suite.h
@@ -52,6 +52,7 @@ public:
inline static const std::string NODE_NAME_JOB = IT_THIN_CLIENT_COMPUTE_TEST + "$NodeNameJob";
inline static const std::string SLEEP_JOB = IT_THIN_CLIENT_COMPUTE_TEST + "$SleepJob";
+ inline static const std::string TO_STRING_JOB = IT_THIN_CLIENT_COMPUTE_TEST + "$ToStringJob";
inline static const std::string CONCAT_JOB = IT_THIN_CLIENT_COMPUTE_TEST + "$ConcatJob";
inline static const std::string ERROR_JOB = IT_THIN_CLIENT_COMPUTE_TEST + "$IgniteExceptionJob";
inline static const std::string ECHO_JOB = IT_THIN_CLIENT_COMPUTE_TEST + "$EchoJob";
diff --git a/modules/platforms/cpp/tests/client-test/schema_synchronization_test.cpp b/modules/platforms/cpp/tests/client-test/schema_synchronization_test.cpp
index 42eb8fcdc6..690ef7df23 100644
--- a/modules/platforms/cpp/tests/client-test/schema_synchronization_test.cpp
+++ b/modules/platforms/cpp/tests/client-test/schema_synchronization_test.cpp
@@ -98,7 +98,7 @@ TEST_F(schema_synchronization_test, upsert_add_column_compute) {
tuple_view.upsert(nullptr, val1);
m_client.get_sql().execute(nullptr, {"ALTER TABLE SCHEMA_SYN_TEST ADD COLUMN VAL2 INT"}, {});
- auto descriptor = job_descriptor::builder().set_job_class_name(NODE_NAME_JOB).build();
+ auto descriptor = job_descriptor::builder(NODE_NAME_JOB).build();
m_client.get_compute().submit_colocated("SCHEMA_SYN_TEST", {key}, descriptor, {}).get_result();
}
diff --git a/modules/platforms/cpp/tests/test-common/basic_auth_test_suite.h b/modules/platforms/cpp/tests/test-common/basic_auth_test_suite.h
index 8f2c8e1074..ae83ef3ed7 100644
--- a/modules/platforms/cpp/tests/test-common/basic_auth_test_suite.h
+++ b/modules/platforms/cpp/tests/test-common/basic_auth_test_suite.h
@@ -97,7 +97,7 @@ public:
auto client = ignite_client::start(cfg, std::chrono::seconds(30));
auto nodes = client.get_cluster_nodes();
- auto descriptor = job_descriptor::builder().set_job_class_name(ENABLE_AUTHN_JOB).build();
+ auto descriptor = job_descriptor::builder(ENABLE_AUTHN_JOB).build();
client.get_compute().submit(nodes, descriptor, {enable ? 1 : 0}).get_result();
} catch (const ignite_error &) {
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/BasicAuthenticatorTests.cs b/modules/platforms/dotnet/Apache.Ignite.Tests/BasicAuthenticatorTests.cs
index 5d7e992ae1..c3d3840769 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/BasicAuthenticatorTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/BasicAuthenticatorTests.cs
@@ -98,7 +98,7 @@ public class BasicAuthenticatorTests : IgniteTestsBase
try
{
- await client.Compute.SubmitAsync(nodes, new JobDescriptor<object>(EnableAuthnJob), enable ? 1 : 0);
+ await client.Compute.SubmitAsync(nodes, new JobDescriptor<int, object>(EnableAuthnJob), enable ? 1 : 0);
}
catch (IgniteClientConnectionException)
{
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/Compute/ComputeClusterAwarenessTests.cs b/modules/platforms/dotnet/Apache.Ignite.Tests/Compute/ComputeClusterAwarenessTests.cs
index cfb82522ab..518b1fa10e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/Compute/ComputeClusterAwarenessTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/Compute/ComputeClusterAwarenessTests.cs
@@ -44,10 +44,10 @@ namespace Apache.Ignite.Tests.Compute
using var client = await IgniteClient.StartAsync(clientCfg);
client.WaitForConnections(3);
- var job = new JobDescriptor<string>(string.Empty);
+ var job = new JobDescriptor<object?, string>(string.Empty);
- IJobExecution<string> exec2 = await client.Compute.SubmitAsync(JobTarget.Node(server2.Node), job);
- IJobExecution<string> exec3 = await client.Compute.SubmitAsync(JobTarget.Node(server3.Node), job);
+ IJobExecution<string> exec2 = await client.Compute.SubmitAsync(JobTarget.Node(server2.Node), job, null);
+ IJobExecution<string> exec3 = await client.Compute.SubmitAsync(JobTarget.Node(server3.Node), job, null);
Assert.AreEqual("s2", await exec2.GetResultAsync());
Assert.AreEqual("s3", await exec3.GetResultAsync());
@@ -66,10 +66,10 @@ namespace Apache.Ignite.Tests.Compute
using var server3 = new FakeServer(nodeName: "s3");
using var client = await server1.ConnectClientAsync();
- var job = new JobDescriptor<string>(string.Empty);
+ var job = new JobDescriptor<object?, string>(string.Empty);
- IJobExecution<string> exec2 = await client.Compute.SubmitAsync(JobTarget.Node(server2.Node), job);
- IJobExecution<string> exec3 = await client.Compute.SubmitAsync(JobTarget.Node(server3.Node), job);
+ IJobExecution<string> exec2 = await client.Compute.SubmitAsync(JobTarget.Node(server2.Node), job, null);
+ IJobExecution<string> exec3 = await client.Compute.SubmitAsync(JobTarget.Node(server3.Node), job, null);
Assert.AreEqual("s1", await exec2.GetResultAsync());
Assert.AreEqual("s1", await exec3.GetResultAsync());
@@ -97,13 +97,13 @@ namespace Apache.Ignite.Tests.Compute
client.WaitForConnections(2);
var nodeNames = new HashSet<string>();
- var job = new JobDescriptor<string>(string.Empty);
+ var job = new JobDescriptor<object?, string>(string.Empty);
for (int i = 0; i < 100; i++)
{
var node = i % 2 == 0 ? server1.Node : server2.Node;
- IJobExecution<string> jobExecution = await client.Compute.SubmitAsync(JobTarget.Node(node), job);
+ IJobExecution<string> jobExecution = await client.Compute.SubmitAsync(JobTarget.Node(node), job, null);
string res = await jobExecution.GetResultAsync();
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/Compute/ComputeTests.cs b/modules/platforms/dotnet/Apache.Ignite.Tests/Compute/ComputeTests.cs
index 1139619f86..03e8213d2c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/Compute/ComputeTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/Compute/ComputeTests.cs
@@ -44,25 +44,27 @@ namespace Apache.Ignite.Tests.Compute
public const string ItThinClientComputeTest = "org.apache.ignite.internal.runner.app.client.ItThinClientComputeTest";
- public static readonly JobDescriptor<string> NodeNameJob = new(ItThinClientComputeTest + "$NodeNameJob");
+ public static readonly JobDescriptor<object?, string> NodeNameJob = new(ItThinClientComputeTest + "$NodeNameJob");
- public static readonly JobDescriptor<string> ConcatJob = new(ItThinClientComputeTest + "$ConcatJob");
+ public static readonly JobDescriptor<string?, string> ConcatJob = new(ItThinClientComputeTest + "$ConcatJob");
- public static readonly JobDescriptor<string> ErrorJob = new(ItThinClientComputeTest + "$IgniteExceptionJob");
+ public static readonly JobDescriptor<string, string> ErrorJob = new(ItThinClientComputeTest + "$IgniteExceptionJob");
- public static readonly JobDescriptor<object> EchoJob = new(ItThinClientComputeTest + "$EchoJob");
+ public static readonly JobDescriptor<object?, object> EchoJob = new(ItThinClientComputeTest + "$EchoJob");
- public static readonly JobDescriptor<string> SleepJob = new(ItThinClientComputeTest + "$SleepJob");
+ public static readonly JobDescriptor<object, string> ToStringJob = new(ItThinClientComputeTest + "$ToStringJob");
- public static readonly JobDescriptor<decimal> DecimalJob = new(ItThinClientComputeTest + "$DecimalJob");
+ public static readonly JobDescriptor<int, string> SleepJob = new(ItThinClientComputeTest + "$SleepJob");
- public static readonly JobDescriptor<string> CreateTableJob = new(PlatformTestNodeRunner + "$CreateTableJob");
+ public static readonly JobDescriptor<string, decimal> DecimalJob = new(ItThinClientComputeTest + "$DecimalJob");
- public static readonly JobDescriptor<string> DropTableJob = new(PlatformTestNodeRunner + "$DropTableJob");
+ public static readonly JobDescriptor<string, string> CreateTableJob = new(PlatformTestNodeRunner + "$CreateTableJob");
- public static readonly JobDescriptor<object> ExceptionJob = new(PlatformTestNodeRunner + "$ExceptionJob");
+ public static readonly JobDescriptor<string, string> DropTableJob = new(PlatformTestNodeRunner + "$DropTableJob");
- public static readonly JobDescriptor<object> CheckedExceptionJob = new(PlatformTestNodeRunner + "$CheckedExceptionJob");
+ public static readonly JobDescriptor<object, object> ExceptionJob = new(PlatformTestNodeRunner + "$ExceptionJob");
+
+ public static readonly JobDescriptor<string, object> CheckedExceptionJob = new(PlatformTestNodeRunner + "$CheckedExceptionJob");
[Test]
public async Task TestGetClusterNodes()
@@ -85,18 +87,18 @@ namespace Apache.Ignite.Tests.Compute
[Test]
public async Task TestExecuteOnSpecificNode()
{
- var res1 = await Client.Compute.SubmitAsync(await GetNodeAsync(0), NodeNameJob, "-", 11);
- var res2 = await Client.Compute.SubmitAsync(await GetNodeAsync(1), NodeNameJob, ":", 22);
+ var res1 = await Client.Compute.SubmitAsync(await GetNodeAsync(0), NodeNameJob, "-11");
+ var res2 = await Client.Compute.SubmitAsync(await GetNodeAsync(1), NodeNameJob, 33);
- Assert.AreEqual(PlatformTestNodeRunner + "-_11", await res1.GetResultAsync());
- Assert.AreEqual(PlatformTestNodeRunner + "_2:_22", await res2.GetResultAsync());
+ Assert.AreEqual(PlatformTestNodeRunner + "-11", await res1.GetResultAsync());
+ Assert.AreEqual(PlatformTestNodeRunner + "_233", await res2.GetResultAsync());
}
[Test]
public async Task TestExecuteOnRandomNode()
{
var jobTarget = JobTarget.AnyNode(await Client.GetClusterNodesAsync());
- var jobExecution = await Client.Compute.SubmitAsync(jobTarget, NodeNameJob);
+ var jobExecution = await Client.Compute.SubmitAsync(jobTarget, NodeNameJob, null);
var res = await jobExecution.GetResultAsync();
var expectedNodeNames = Enumerable.Range(1, 4)
@@ -109,8 +111,8 @@ namespace Apache.Ignite.Tests.Compute
[Test]
public async Task TestExecuteResultTypeMismatchThrowsInvalidCastException()
{
- var jobDescriptor = new JobDescriptor<Guid>(NodeNameJob.JobClassName);
- var jobExecution = await Client.Compute.SubmitAsync(await GetNodeAsync(0), jobDescriptor);
+ var jobDescriptor = new JobDescriptor<object?, Guid>(NodeNameJob.JobClassName);
+ var jobExecution = await Client.Compute.SubmitAsync(await GetNodeAsync(0), jobDescriptor, null);
Assert.ThrowsAsync<InvalidCastException>(async () => await jobExecution.GetResultAsync());
}
@@ -155,24 +157,10 @@ namespace Apache.Ignite.Tests.Compute
Assert.AreEqual(nodes[3].Name + "123", await res4.GetResultAsync());
}
- [Test]
- public async Task TestExecuteWithArgs()
- {
- var res = await Client.Compute.SubmitAsync(
- await GetNodeAsync(0),
- ConcatJob,
- 1.1,
- Guid.Empty,
- "3",
- null);
-
- Assert.AreEqual("1.1_00000000-0000-0000-0000-000000000000_3_null", await res.GetResultAsync());
- }
-
[Test]
public async Task TestExecuteWithNullArgs()
{
- var res = await Client.Compute.SubmitAsync(await GetNodeAsync(0), ConcatJob, args: null);
+ var res = await Client.Compute.SubmitAsync(await GetNodeAsync(0), ConcatJob, null);
Assert.IsNull(await res.GetResultAsync());
}
@@ -242,7 +230,7 @@ namespace Apache.Ignite.Tests.Compute
await Test(decimal.MinValue);
await Test(decimal.MaxValue);
- await Test(new byte[] { 1, 255 });
+ await Test(new byte[] { 1, 255 }, "[1, -1]");
await Test("Ignite 🔥");
await Test(new BitArray(new[] { byte.MaxValue }), "{0, 1, 2, 3, 4, 5, 6, 7}");
await Test(LocalDate.MinIsoValue, "-9998-01-01");
@@ -263,11 +251,17 @@ namespace Apache.Ignite.Tests.Compute
async Task Test(object val, string? expectedStr = null)
{
var nodes = JobTarget.AnyNode(await Client.GetClusterNodesAsync());
- var str = expectedStr ?? val.ToString()!.Replace("E+", "E");
- IJobExecution<object> resExec = await Client.Compute.SubmitAsync(nodes, EchoJob, val, str);
+
+ IJobExecution<object> resExec = await Client.Compute.SubmitAsync(nodes, EchoJob, val);
object res = await resExec.GetResultAsync();
Assert.AreEqual(val, res);
+
+ var strExec = await Client.Compute.SubmitAsync(nodes, ToStringJob, val);
+ var str = await strExec.GetResultAsync();
+
+ var expectedStr0 = expectedStr ?? val.ToString()!.Replace("E+", "E");
+ Assert.AreEqual(expectedStr0, str);
}
}
@@ -289,15 +283,15 @@ namespace Apache.Ignite.Tests.Compute
client.WaitForConnections(proxies.Count);
var keyTuple = new IgniteTuple { [KeyCol] = key };
- var resNodeName = await client.Compute.SubmitAsync(JobTarget.Colocated(TableName, keyTuple), NodeNameJob);
+ var resNodeName = await client.Compute.SubmitAsync(JobTarget.Colocated(TableName, keyTuple), NodeNameJob, null);
var requestTargetNodeName = GetRequestTargetNodeName(proxies, ClientOp.ComputeExecuteColocated);
var keyPoco = new Poco { Key = key };
- var resNodeName2 = await client.Compute.SubmitAsync(JobTarget.Colocated(TableName, keyPoco), NodeNameJob);
+ var resNodeName2 = await client.Compute.SubmitAsync(JobTarget.Colocated(TableName, keyPoco), NodeNameJob, null);
var requestTargetNodeName2 = GetRequestTargetNodeName(proxies, ClientOp.ComputeExecuteColocated);
var keyPocoStruct = new PocoStruct(key, null);
- var resNodeName3 = await client.Compute.SubmitAsync(JobTarget.Colocated(TableName, keyPocoStruct), NodeNameJob);
+ var resNodeName3 = await client.Compute.SubmitAsync(JobTarget.Colocated(TableName, keyPocoStruct), NodeNameJob, null);
var requestTargetNodeName3 = GetRequestTargetNodeName(proxies, ClientOp.ComputeExecuteColocated);
var nodeName = nodeIdx == 1 ? string.Empty : "_" + nodeIdx;
@@ -320,7 +314,7 @@ namespace Apache.Ignite.Tests.Compute
public void TestExecuteColocatedThrowsWhenTableDoesNotExist()
{
var ex = Assert.ThrowsAsync<IgniteClientException>(async () =>
- await Client.Compute.SubmitAsync(JobTarget.Colocated("unknownTable", new IgniteTuple()), EchoJob));
+ await Client.Compute.SubmitAsync(JobTarget.Colocated("unknownTable", new IgniteTuple()), EchoJob, null));
Assert.AreEqual("Table 'unknownTable' does not exist.", ex!.Message);
}
@@ -329,7 +323,7 @@ namespace Apache.Ignite.Tests.Compute
public void TestExecuteColocatedThrowsWhenKeyColumnIsMissing()
{
var ex = Assert.ThrowsAsync<ArgumentException>(async () =>
- await Client.Compute.SubmitAsync(JobTarget.Colocated(TableName, new IgniteTuple { ["VAL"] = "1" }), EchoJob));
+ await Client.Compute.SubmitAsync(JobTarget.Colocated(TableName, new IgniteTuple { ["VAL"] = "1" }), EchoJob, null));
Assert.AreEqual(
"Can't map 'IgniteTuple { VAL = 1 }' to columns 'Int64 KEY, String VAL'. Matching fields not found.",
@@ -347,7 +341,7 @@ namespace Apache.Ignite.Tests.Compute
try
{
var keyTuple = new IgniteTuple { [KeyCol] = 1L };
- var resNodeNameExec = await Client.Compute.SubmitAsync(JobTarget.Colocated(tableName, keyTuple), NodeNameJob);
+ var resNodeNameExec = await Client.Compute.SubmitAsync(JobTarget.Colocated(tableName, keyTuple), NodeNameJob, null);
var resNodeName = await resNodeNameExec.GetResultAsync();
// Drop table and create a new one with a different ID, then execute a computation again.
@@ -364,7 +358,7 @@ namespace Apache.Ignite.Tests.Compute
table.SetFieldValue("_partitionAssignment", null);
}
- var resNodeName2Exec = await Client.Compute.SubmitAsync(JobTarget.Colocated(tableName, keyTuple), NodeNameJob);
+ var resNodeName2Exec = await Client.Compute.SubmitAsync(JobTarget.Colocated(tableName, keyTuple), NodeNameJob, null);
var resNodeName2 = await resNodeName2Exec.GetResultAsync();
Assert.AreEqual(resNodeName, resNodeName2);
@@ -386,8 +380,8 @@ namespace Apache.Ignite.Tests.Compute
{
await Client.Sql.ExecuteAsync(null, $"CREATE TABLE {tableName} (KEY BIGINT PRIMARY KEY, VAL VARCHAR)");
- var exec1 = await Client.Compute.SubmitAsync(JobTarget.Colocated(tableName, tupleKey), NodeNameJob);
- var exec2 = await Client.Compute.SubmitAsync(JobTarget.Colocated(tableName, key), NodeNameJob);
+ var exec1 = await Client.Compute.SubmitAsync(JobTarget.Colocated(tableName, tupleKey), NodeNameJob, null);
+ var exec2 = await Client.Compute.SubmitAsync(JobTarget.Colocated(tableName, key), NodeNameJob, null);
var res1 = await exec1.GetResultAsync();
var res2 = await exec2.GetResultAsync();
@@ -442,14 +436,16 @@ namespace Apache.Ignite.Tests.Compute
var res = await client.Compute.SubmitAsync(
await GetNodeAsync(1),
- new JobDescriptor<string>(FakeServer.GetDetailsJob, units));
+ new JobDescriptor<object?, string>(FakeServer.GetDetailsJob, units),
+ null);
StringAssert.Contains("Units = unit-latest|latest, unit1|1.0.0", await res.GetResultAsync());
// Lazy enumerable.
var res2 = await client.Compute.SubmitAsync(
await GetNodeAsync(1),
- new JobDescriptor<string>(FakeServer.GetDetailsJob, units.Reverse()));
+ new JobDescriptor<object?, string>(FakeServer.GetDetailsJob, units.Reverse()),
+ null);
StringAssert.Contains("Units = unit1|1.0.0, unit-latest|latest", await res2.GetResultAsync());
@@ -457,7 +453,8 @@ namespace Apache.Ignite.Tests.Compute
var keyTuple = new IgniteTuple { ["ID"] = 1 };
var res3 = await client.Compute.SubmitAsync(
JobTarget.Colocated(FakeServer.ExistingTableName, keyTuple),
- new JobDescriptor<string>(FakeServer.GetDetailsJob, units));
+ new JobDescriptor<object?, string>(FakeServer.GetDetailsJob, units),
+ null);
StringAssert.Contains("Units = unit-latest|latest, unit1|1.0.0", await res3.GetResultAsync());
}
@@ -474,7 +471,7 @@ namespace Apache.Ignite.Tests.Compute
};
var ex = Assert.ThrowsAsync<IgniteException>(
- async () => await Client.Compute.SubmitAsync(await GetNodeAsync(1), job));
+ async () => await Client.Compute.SubmitAsync(await GetNodeAsync(1), job, null));
StringAssert.Contains("Deployment unit unit-latest:latest doesn't exist", ex!.Message);
}
@@ -492,7 +489,7 @@ namespace Apache.Ignite.Tests.Compute
};
var ex = Assert.ThrowsAsync<IgniteException>(
- async () => await Client.Compute.SubmitAsync(JobTarget.Colocated(TableName, keyTuple), job));
+ async () => await Client.Compute.SubmitAsync(JobTarget.Colocated(TableName, keyTuple), job, null));
StringAssert.Contains("Deployment unit unit-latest:latest doesn't exist", ex!.Message);
}
@@ -509,7 +506,7 @@ namespace Apache.Ignite.Tests.Compute
};
var ex = Assert.ThrowsAsync<ArgumentNullException>(
- async () => await Client.Compute.SubmitAsync(await GetNodeAsync(1), job));
+ async () => await Client.Compute.SubmitAsync(await GetNodeAsync(1), job, null));
Assert.AreEqual("Value cannot be null. (Parameter 'unit.Name')", ex!.Message);
}
@@ -526,7 +523,7 @@ namespace Apache.Ignite.Tests.Compute
};
var ex = Assert.ThrowsAsync<ArgumentException>(
- async () => await Client.Compute.SubmitAsync(await GetNodeAsync(1), job));
+ async () => await Client.Compute.SubmitAsync(await GetNodeAsync(1), job, null));
Assert.AreEqual("The value cannot be an empty string. (Parameter 'unit.Name')", ex!.Message);
}
@@ -543,7 +540,7 @@ namespace Apache.Ignite.Tests.Compute
};
var ex = Assert.ThrowsAsync<ArgumentNullException>(
- async () => await Client.Compute.SubmitAsync(await GetNodeAsync(1), job));
+ async () => await Client.Compute.SubmitAsync(await GetNodeAsync(1), job, null));
Assert.AreEqual("Value cannot be null. (Parameter 'unit.Version')", ex!.Message);
}
@@ -560,7 +557,7 @@ namespace Apache.Ignite.Tests.Compute
};
var ex = Assert.ThrowsAsync<ArgumentException>(
- async () => await Client.Compute.SubmitAsync(await GetNodeAsync(1), job));
+ async () => await Client.Compute.SubmitAsync(await GetNodeAsync(1), job, null));
Assert.AreEqual("The value cannot be an empty string. (Parameter 'unit.Version')", ex!.Message);
}
@@ -664,7 +661,7 @@ namespace Apache.Ignite.Tests.Compute
public async Task TestJobExecutionOptionsPropagation()
{
// ReSharper disable once WithExpressionModifiesAllMembers
- var job = new JobDescriptor<string>(FakeServer.GetDetailsJob)
+ var job = new JobDescriptor<object?, string>(FakeServer.GetDetailsJob)
{
Options = JobExecutionOptions.Default with
{
@@ -677,15 +674,15 @@ namespace Apache.Ignite.Tests.Compute
using var server = new FakeServer();
using var client = await server.ConnectClientAsync();
- var defaultRes = await client.Compute.SubmitAsync(await GetNodeAsync(1), job with { Options = default });
+ var defaultRes = await client.Compute.SubmitAsync(await GetNodeAsync(1), job with { Options = default }, null);
StringAssert.Contains("priority = 0, maxRetries = 0", await defaultRes.GetResultAsync());
- var res = await client.Compute.SubmitAsync(await GetNodeAsync(1), job);
+ var res = await client.Compute.SubmitAsync(await GetNodeAsync(1), job, null);
StringAssert.Contains("priority = 999, maxRetries = 66", await res.GetResultAsync());
// Colocated.
var keyTuple = new IgniteTuple { ["ID"] = 1 };
- var colocatedRes = await client.Compute.SubmitAsync(JobTarget.Colocated(FakeServer.ExistingTableName, keyTuple), job);
+ var colocatedRes = await client.Compute.SubmitAsync(JobTarget.Colocated(FakeServer.ExistingTableName, keyTuple), job, null);
StringAssert.Contains("priority = 999, maxRetries = 66", await colocatedRes.GetResultAsync());
}
@@ -697,7 +694,7 @@ namespace Apache.Ignite.Tests.Compute
[TestCase("1.123456789", 5)]
public async Task TestBigDecimalPropagation(string number, int scale)
{
- var res = await Client.Compute.SubmitAsync(await GetNodeAsync(1), DecimalJob, number, scale);
+ var res = await Client.Compute.SubmitAsync(await GetNodeAsync(1), DecimalJob, $"{number},{scale}");
var resVal = await res.GetResultAsync();
var expected = decimal.Parse(number, NumberStyles.Float);
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs b/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs
index 8814df0774..669b73167d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs
@@ -366,7 +366,7 @@ namespace Apache.Ignite.Tests
reader.ReadBoolean(); // returnResults.
var payloadTupleSize = reader.ReadInt32();
- var payloadItemCount = payloadTupleSize - 4; // NOTE: Ignores args.
+ var payloadItemCount = payloadTupleSize - 6; // NOTE: Ignores args.
StreamerRowCount += payloadItemCount;
if (MultiRowOperationDelayPerRow > TimeSpan.Zero)
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/PartitionAwarenessRealClusterTests.cs b/modules/platforms/dotnet/Apache.Ignite.Tests/PartitionAwarenessRealClusterTests.cs
index e1633abf23..bbafccaff9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/PartitionAwarenessRealClusterTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/PartitionAwarenessRealClusterTests.cs
@@ -53,7 +53,8 @@ public class PartitionAwarenessRealClusterTests : IgniteTestsBase
var primaryNodeNameExec = await client.Compute.SubmitAsync(
JobTarget.Colocated(TableName, keyTuple),
- ComputeTests.NodeNameJob);
+ ComputeTests.NodeNameJob,
+ null);
var primaryNodeName = await primaryNodeNameExec.GetResultAsync();
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/PartitionAwarenessTests.cs b/modules/platforms/dotnet/Apache.Ignite.Tests/PartitionAwarenessTests.cs
index d0ad654b42..143733c5f2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/PartitionAwarenessTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/PartitionAwarenessTests.cs
@@ -128,7 +128,8 @@ public class PartitionAwarenessTests
new[] { 1 }.ToAsyncEnumerable(),
keySelector: x => x,
payloadSelector: x => x.ToString(),
- new("x")),
+ new ReceiverDescriptor<object?>("x"),
+ null),
ClientOp.StreamerWithReceiverBatchSend);
[Test]
@@ -142,8 +143,10 @@ public class PartitionAwarenessTests
var options = new DataStreamerOptions { PageSize = 1 };
var data = producer.Reader.ReadAllAsync();
+ var receiverDescriptor = new ReceiverDescriptor<object?>("x");
+
var streamerTask = withReceiver
- ? recordView.StreamDataAsync(data, x => x, x => x.ToString(), new("x"), null, options)
+ ? recordView.StreamDataAsync(data, x => x, x => x.ToString(), receiverDescriptor, null, options)
: recordView.StreamDataAsync(data, options);
Func<ITransaction?, Task> action = async _ =>
@@ -360,12 +363,12 @@ public class PartitionAwarenessTests
// Warm up.
var jobTarget = JobTarget.Colocated(FakeServer.ExistingTableName, key);
- var jobDescriptor = new JobDescriptor<object?>("job");
+ var jobDescriptor = new JobDescriptor<object?, object?>("job");
- await client.Compute.SubmitAsync(jobTarget, jobDescriptor);
+ await client.Compute.SubmitAsync(jobTarget, jobDescriptor, null);
await AssertOpOnNode(
- _ => client.Compute.SubmitAsync(jobTarget, jobDescriptor),
+ _ => client.Compute.SubmitAsync(jobTarget, jobDescriptor, null),
ClientOp.ComputeExecuteColocated,
expectedNode);
}
@@ -379,13 +382,13 @@ public class PartitionAwarenessTests
var key = new SimpleKey(keyId);
var jobTarget = JobTarget.Colocated(FakeServer.ExistingTableName, key);
- var jobDescriptor = new JobDescriptor<object?>("job");
+ var jobDescriptor = new JobDescriptor<object?, object?>("job");
// Warm up.
- await client.Compute.SubmitAsync(jobTarget, jobDescriptor);
+ await client.Compute.SubmitAsync(jobTarget, jobDescriptor, null);
await AssertOpOnNode(
- _ => client.Compute.SubmitAsync(jobTarget, jobDescriptor),
+ _ => client.Compute.SubmitAsync(jobTarget, jobDescriptor, null),
ClientOp.ComputeExecuteColocated,
expectedNode);
}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/Proto/ColocationHashTests.cs b/modules/platforms/dotnet/Apache.Ignite.Tests/Proto/ColocationHashTests.cs
index 7e43a44a35..af86ea0f99 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/Proto/ColocationHashTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/Proto/ColocationHashTests.cs
@@ -187,7 +187,7 @@ public class ColocationHashTests : IgniteTestsBase
var schema = schemas[1].GetAwaiter().GetResult();
var clusterNodes = await Client.GetClusterNodesAsync();
var jobTarget = JobTarget.AnyNode(clusterNodes);
- var job = new JobDescriptor<int>(TableRowColocationHashJob);
+ var job = new JobDescriptor<object, int>(TableRowColocationHashJob);
for (int i = 0; i < 100; i++)
{
@@ -196,11 +196,20 @@ public class ColocationHashTests : IgniteTestsBase
using var writer = ProtoCommon.GetMessageWriter();
var (clientColocationHash, _) = ser.Write(writer, null, schema, key);
- var serverColocationHashExec = await Client.Compute.SubmitAsync(jobTarget, job, tableName, i);
+ var serverColocationHashExec = await Client.Compute.SubmitAsync(jobTarget, job, GetArg(tableName, i));
var serverColocationHash = await serverColocationHashExec.GetResultAsync();
Assert.AreEqual(serverColocationHash, clientColocationHash, key.ToString());
}
+
+ static byte[] GetArg(string tableName, int i)
+ {
+ using var argBuilder = new BinaryTupleBuilder(2);
+ argBuilder.AppendString(tableName);
+ argBuilder.AppendInt(i);
+
+ return argBuilder.Build().ToArray();
+ }
}
private static (byte[] Bytes, int Hash) WriteAsBinaryTuple(IReadOnlyCollection<object> arr, int timePrecision, int timestampPrecision)
@@ -335,13 +344,21 @@ public class ColocationHashTests : IgniteTestsBase
IJobExecution<int> jobExecution = await Client.Compute.SubmitAsync(
target,
- new JobDescriptor<int>(ColocationHashJob),
- count,
- bytes,
- timePrecision,
- timestampPrecision);
+ new JobDescriptor<object, int>(ColocationHashJob),
+ GetArg());
return await jobExecution.GetResultAsync();
+
+ byte[] GetArg()
+ {
+ using var argBuilder = new BinaryTupleBuilder(4);
+ argBuilder.AppendInt(count);
+ argBuilder.AppendInt(timePrecision);
+ argBuilder.AppendInt(timestampPrecision);
+ argBuilder.AppendBytes(bytes);
+
+ return argBuilder.Build().ToArray();
+ }
}
private record TestIndexProvider(Func<int, int> ColumnOrderDelegate, int HashedColumnCount) : IHashedColumnIndexProvider
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/Table/DataStreamerTests.cs b/modules/platforms/dotnet/Apache.Ignite.Tests/Table/DataStreamerTests.cs
index 1103400fc0..89a0b548d0 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/Table/DataStreamerTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/Table/DataStreamerTests.cs
@@ -52,11 +52,11 @@ public class DataStreamerTests : IgniteTestsBase
private const int DeletedKey = Count + 1;
- private static readonly ReceiverDescriptor<string> TestReceiver = new(TestReceiverClassName);
+ private static readonly ReceiverDescriptor<string?, string> TestReceiver = new(TestReceiverClassName);
- private static readonly ReceiverDescriptor TestReceiverNoResults = new(TestReceiverClassName);
+ private static readonly ReceiverDescriptor<object?> TestReceiverNoResults = new(TestReceiverClassName);
- private static readonly ReceiverDescriptor<object> EchoArgsReceiver = new(EchoArgsReceiverClassName);
+ private static readonly ReceiverDescriptor<object, object> EchoArgsReceiver = new(EchoArgsReceiverClassName);
private static readonly object[] AllSupportedTypes =
{
@@ -166,12 +166,12 @@ public class DataStreamerTests : IgniteTestsBase
if (withReceiver)
{
- _ = TupleView.StreamDataAsync<IIgniteTuple, string>(
+ _ = TupleView.StreamDataAsync(
GetTuplesWithDelay(cts.Token),
x => GetTuple((long)x[0]!),
x => $"{x[0]}-value",
TestReceiverNoResults,
- receiverArgs: new object[] { Table.Name, "arg1", 22 },
+ receiverArg: GetReceiverArg(Table.Name, "arg1", 22),
options: options);
}
else
@@ -231,7 +231,7 @@ public class DataStreamerTests : IgniteTestsBase
// Receiver without results.
case false:
- await Table.RecordBinaryView.StreamDataAsync<IIgniteTuple, string>(
+ await Table.RecordBinaryView.StreamDataAsync(
Array.Empty<IIgniteTuple>().ToAsyncEnumerable(),
t => t,
t => t.ToString()!,
@@ -284,11 +284,12 @@ public class DataStreamerTests : IgniteTestsBase
var table = await client.Tables.GetTableAsync(FakeServer.ExistingTableName);
var ex = Assert.ThrowsAsync<IgniteClientConnectionException>(
- async () => await table!.RecordBinaryView.StreamDataAsync<IIgniteTuple, string>(
+ async () => await table!.RecordBinaryView.StreamDataAsync(
GetFakeServerData(10_000),
keySelector: t => t,
payloadSelector: t => t[0]!.ToString()!,
- TestReceiverNoResults));
+ TestReceiverNoResults,
+ null));
StringAssert.StartsWith("Operation StreamerWithReceiverBatchSend failed after 16 retries", ex!.Message);
}
@@ -318,7 +319,8 @@ public class DataStreamerTests : IgniteTestsBase
GetFakeServerData(count),
keySelector: t => t,
payloadSelector: t => t[0]!.ToString()!,
- TestReceiverNoResults);
+ TestReceiverNoResults,
+ null);
}
else
{
@@ -380,7 +382,7 @@ public class DataStreamerTests : IgniteTestsBase
keySelector: x => GetTuple(x),
payloadSelector: x => $"{x}-value{x * 10}",
receiver: TestReceiverNoResults,
- receiverArgs: new object[] { Table.Name, "arg1", 22 },
+ receiverArg: GetReceiverArg(Table.Name, "arg1", 22),
options: DataStreamerOptions.Default);
for (int i = 0; i < Count; i++)
@@ -400,7 +402,7 @@ public class DataStreamerTests : IgniteTestsBase
keySelector: x => GetTuple(x),
payloadSelector: x => $"{x}-value{x * 10}",
TestReceiver,
- receiverArgs: new object[] { Table.Name, "arg1", 22 },
+ receiverArg: GetReceiverArg(Table.Name, "arg1", 22),
options: DataStreamerOptions.Default);
var resultSet = await results.ToHashSetAsync();
@@ -428,7 +430,7 @@ public class DataStreamerTests : IgniteTestsBase
keySelector: x => GetPoco(x),
payloadSelector: x => $"{x}-value{x * 10}",
receiver: TestReceiverNoResults,
- receiverArgs: new object[] { Table.Name, "arg1", 22 },
+ receiverArg: GetReceiverArg(Table.Name, "arg1", 22),
options: DataStreamerOptions.Default);
for (int i = 0; i < Count; i++)
@@ -448,7 +450,7 @@ public class DataStreamerTests : IgniteTestsBase
keySelector: x => GetPoco(x),
payloadSelector: x => $"{x}-value{x * 10}",
TestReceiver,
- receiverArgs: new object[] { Table.Name, "arg1", 22 },
+ receiverArg: GetReceiverArg(Table.Name, "arg1", 22),
options: DataStreamerOptions.Default);
var resultSet = await results.ToHashSetAsync();
@@ -476,7 +478,7 @@ public class DataStreamerTests : IgniteTestsBase
keySelector: x => new KeyValuePair<IIgniteTuple, IIgniteTuple>(GetTuple(x), new IgniteTuple()),
payloadSelector: x => $"{x}-value{x * 10}",
receiver: TestReceiverNoResults,
- receiverArgs: new object[] { Table.Name, "arg1", 22 });
+ receiverArg: GetReceiverArg(Table.Name, "arg1", 22));
for (int i = 0; i < Count; i++)
{
@@ -495,7 +497,7 @@ public class DataStreamerTests : IgniteTestsBase
keySelector: x => new KeyValuePair<IIgniteTuple, IIgniteTuple>(GetTuple(x), new IgniteTuple()),
payloadSelector: x => $"{x}-value{x * 10}",
TestReceiver,
- receiverArgs: new object[] { Table.Name, "arg1", 22 });
+ receiverArg: GetReceiverArg(Table.Name, "arg1", 22));
var resultSet = await results.ToHashSetAsync();
@@ -522,7 +524,7 @@ public class DataStreamerTests : IgniteTestsBase
keySelector: x => new KeyValuePair<long, Poco>(x, null!),
payloadSelector: x => $"{x}-value{x * 10}",
receiver: TestReceiverNoResults,
- receiverArgs: new object[] { Table.Name, "arg11", 55});
+ receiverArg: GetReceiverArg(Table.Name, "arg11", 55));
for (int i = 0; i < Count; i++)
{
@@ -541,7 +543,7 @@ public class DataStreamerTests : IgniteTestsBase
keySelector: x => new KeyValuePair<long, Poco>(x, null!),
payloadSelector: x => $"{x}-value{x * 10}",
TestReceiver,
- receiverArgs: new object[] { Table.Name, "arg11", 55});
+ receiverArg: GetReceiverArg(Table.Name, "arg11", 55));
var resultSet = await results.ToHashSetAsync();
@@ -568,7 +570,8 @@ public class DataStreamerTests : IgniteTestsBase
Enumerable.Range(0, 1).ToAsyncEnumerable(),
keySelector: x => GetTuple(x),
payloadSelector: _ => string.Empty,
- new("_unknown_")));
+ new ReceiverDescriptor<object?>("_unknown_"),
+ null));
Assert.AreEqual("Streamer receiver failed: Cannot load receiver class by name '_unknown_'", ex.Message);
}
@@ -577,12 +580,12 @@ public class DataStreamerTests : IgniteTestsBase
public void TestReceiverException()
{
var ex = Assert.ThrowsAsync<IgniteException>(async () =>
- await PocoView.StreamDataAsync<int, string>(
+ await PocoView.StreamDataAsync(
Enumerable.Range(0, 1).ToAsyncEnumerable(),
keySelector: x => GetPoco(x),
payloadSelector: _ => string.Empty,
receiver: TestReceiverNoResults,
- receiverArgs: new object[] { "throw", "throw", 1 }));
+ receiverArg: GetReceiverArg("throw", "throw", 1)));
Assert.AreEqual("Streamer receiver failed: Job execution failed: java.lang.ArithmeticException: Test exception: 1", ex.Message);
}
@@ -596,7 +599,7 @@ public class DataStreamerTests : IgniteTestsBase
keySelector: x => GetPoco(x),
payloadSelector: _ => string.Empty,
TestReceiver,
- receiverArgs: new object[] { "throw", "throw", 1 }).ToListAsync());
+ receiverArg: GetReceiverArg("throw", "throw", 1)).ToListAsync());
Assert.AreEqual("Streamer receiver failed: Job execution failed: java.lang.ArithmeticException: Test exception: 1", ex.Message);
}
@@ -605,12 +608,12 @@ public class DataStreamerTests : IgniteTestsBase
public void TestReceiverSelectorException([Values(true, false)] bool keySelector)
{
var ex = Assert.ThrowsAsync<DataException>(async () =>
- await PocoView.StreamDataAsync<int, string>(
+ await PocoView.StreamDataAsync<int, object, object?>(
Enumerable.Range(0, 1).ToAsyncEnumerable(),
keySelector: x => keySelector ? throw new DataException("key") : GetPoco(x),
payloadSelector: _ => throw new DataException("payload"),
receiver: TestReceiverNoResults,
- receiverArgs: new object[] { "throw", "throw", 1 }));
+ receiverArg: GetReceiverArg("throw", "throw", 1)));
Assert.AreEqual(keySelector ? "key" : "payload", ex.Message);
}
@@ -657,12 +660,12 @@ public class DataStreamerTests : IgniteTestsBase
public void TestWithReceiverDifferentDataTypesThrows()
{
var ex = Assert.ThrowsAsync<InvalidOperationException>(async () =>
- await PocoView.StreamDataAsync<object, object>(
+ await PocoView.StreamDataAsync(
new object[] { 1, "2" }.ToAsyncEnumerable(),
keySelector: _ => new Poco(),
payloadSelector: x => x,
receiver: TestReceiverNoResults,
- receiverArgs: new object[] { TableName, "1", 2 }));
+ receiverArg: null));
Assert.AreEqual(
"All streamer items returned by payloadSelector must be of the same type. Expected: System.Int32, actual: System.String.",
@@ -673,12 +676,12 @@ public class DataStreamerTests : IgniteTestsBase
public void TestWithReceiverNullItemThrows()
{
var ex = Assert.ThrowsAsync<ArgumentNullException>(async () =>
- await PocoView.StreamDataAsync<object, object>(
+ await PocoView.StreamDataAsync(
new object[] { "2", null! }.ToAsyncEnumerable(),
keySelector: _ => new Poco(),
payloadSelector: x => x,
receiver: TestReceiverNoResults,
- receiverArgs: new object[] { TableName, "1", 2 }));
+ receiverArg: null));
Assert.AreEqual(
"Value cannot be null. (Parameter 'payload')",
@@ -688,12 +691,12 @@ public class DataStreamerTests : IgniteTestsBase
[TestCaseSource(nameof(AllSupportedTypes))]
public async Task TestEchoReceiverAllDataTypes(object arg)
{
- var res = await PocoView.StreamDataAsync<object, object, object>(
+ var res = await PocoView.StreamDataAsync<object, object, object, object>(
new object[] { 1 }.ToAsyncEnumerable(),
keySelector: _ => new Poco(),
payloadSelector: x => x.ToString()!,
EchoArgsReceiver,
- receiverArgs: new[] { arg }).SingleAsync();
+ receiverArg: arg).SingleAsync();
Assert.AreEqual(arg, res);
}
@@ -706,7 +709,7 @@ public class DataStreamerTests : IgniteTestsBase
keySelector: x => GetPoco(x),
payloadSelector: x => $"{x}-value{x * 10}",
TestReceiver,
- receiverArgs: new object[] { Table.Name, "arg1", 22 },
+ receiverArg: GetReceiverArg(Table.Name, "arg1", 22),
options: DataStreamerOptions.Default with { PageSize = 1 });
// Read only part of the results.
@@ -727,12 +730,12 @@ public class DataStreamerTests : IgniteTestsBase
[Test]
public async Task TestResultConsumerCancellation()
{
- IAsyncEnumerable<string> results = PocoView.StreamDataAsync<int, string, string>(
+ IAsyncEnumerable<string> results = PocoView.StreamDataAsync<int, string, string?, string>(
Enumerable.Range(0, Count).ToAsyncEnumerable(),
keySelector: x => GetPoco(x),
payloadSelector: x => $"{x}-value{x * 10}",
TestReceiver,
- receiverArgs: new object[] { Table.Name, "arg1", 22 },
+ receiverArg: GetReceiverArg(Table.Name, "arg1", 22),
options: DataStreamerOptions.Default with { PageSize = 1 });
var cts = new CancellationTokenSource();
@@ -767,17 +770,20 @@ public class DataStreamerTests : IgniteTestsBase
}
}
+ private static string GetReceiverArg(string tableName, string arg1, int arg2) =>
+ $"{tableName}:{arg1}:{arg2}";
+
private async Task CheckReceiverValue(object value, string expectedClassName, string expectedValue)
{
var key1 = 1L;
var key2 = 2L;
- await PocoView.StreamDataAsync<int, object>(
+ await PocoView.StreamDataAsync(
Enumerable.Range(0, 1).ToAsyncEnumerable(),
keySelector: x => GetPoco(x),
payloadSelector: _ => value,
- receiver: new ReceiverDescriptor(UpsertElementTypeNameReceiverClassName),
- receiverArgs: new object[] { TableName, key1, key2 });
+ receiver: new ReceiverDescriptor<string>(UpsertElementTypeNameReceiverClassName),
+ receiverArg: $"{TableName}:{key1}:{key2}");
var className = (await TupleView.GetAsync(null, GetTuple(key1))).Value[1];
var valueStr = (await TupleView.GetAsync(null, GetTuple(key2))).Value[1];
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/Table/SchemaSynchronizationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Tests/Table/SchemaSynchronizationTest.cs
index 9da05d08d0..44f1cbcf8b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/Table/SchemaSynchronizationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/Table/SchemaSynchronizationTest.cs
@@ -98,7 +98,8 @@ public class SchemaSynchronizationTest : IgniteTestsBase
case TestMode.Compute:
await Client.Compute.SubmitAsync(
JobTarget.Colocated(table.Name, rec2),
- ComputeTests.NodeNameJob);
+ ComputeTests.NodeNameJob,
+ null);
break;
default:
@@ -156,7 +157,8 @@ public class SchemaSynchronizationTest : IgniteTestsBase
// ExecuteColocated requires key part only.
await Client.Compute.SubmitAsync(
JobTarget.Colocated(table.Name, rec),
- ComputeTests.NodeNameJob);
+ ComputeTests.NodeNameJob,
+ null);
break;
default:
@@ -297,7 +299,8 @@ public class SchemaSynchronizationTest : IgniteTestsBase
case TestMode.Compute:
var jobExecution = await Client.Compute.SubmitAsync(
JobTarget.Colocated(table.Name, new Poco(1, "foo")),
- ComputeTests.NodeNameJob);
+ ComputeTests.NodeNameJob,
+ null);
await jobExecution.GetResultAsync();
diff --git a/modules/platforms/dotnet/Apache.Ignite/ClientOperationType.cs b/modules/platforms/dotnet/Apache.Ignite/ClientOperationType.cs
index c64b527037..3de6312be0 100644
--- a/modules/platforms/dotnet/Apache.Ignite/ClientOperationType.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/ClientOperationType.cs
@@ -117,7 +117,7 @@ namespace Apache.Ignite
TupleContainsKey,
/// <summary>
- /// Compute (<see cref="ICompute.SubmitAsync{TTarget,TResult}"/>, <see cref="ICompute.SubmitBroadcast{T}"/>).
+ /// Compute (<see cref="ICompute.SubmitAsync{TTarget,TArg,TResult}"/>, <see cref="ICompute.SubmitBroadcast{TArg,TResult}"/>).
/// </summary>
ComputeExecute,
diff --git a/modules/platforms/dotnet/Apache.Ignite/Compute/ICompute.cs b/modules/platforms/dotnet/Apache.Ignite/Compute/ICompute.cs
index 6a3c349b97..315eaba239 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Compute/ICompute.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Compute/ICompute.cs
@@ -31,14 +31,15 @@ public interface ICompute
/// </summary>
/// <param name="target">Job execution target.</param>
/// <param name="jobDescriptor">Job descriptor.</param>
- /// <param name="args">Job arguments.</param>
+ /// <param name="arg">Job arguments.</param>
/// <typeparam name="TTarget">Job target type.</typeparam>
+ /// <typeparam name="TArg">Job argument type.</typeparam>
/// <typeparam name="TResult">Job result type.</typeparam>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
- Task<IJobExecution<TResult>> SubmitAsync<TTarget, TResult>(
+ Task<IJobExecution<TResult>> SubmitAsync<TTarget, TArg, TResult>(
IJobTarget<TTarget> target,
- JobDescriptor<TResult> jobDescriptor,
- params object?[]? args)
+ JobDescriptor<TArg, TResult> jobDescriptor,
+ TArg arg)
where TTarget : notnull;
/// <summary>
@@ -46,11 +47,12 @@ public interface ICompute
/// </summary>
/// <param name="nodes">Nodes to use for the job execution.</param>
/// <param name="jobDescriptor">Job descriptor.</param>
- /// <param name="args">Job arguments.</param>
+ /// <param name="arg">Job arguments.</param>
+ /// <typeparam name="TArg">Job argument type.</typeparam>
/// <typeparam name="TResult">Job result type.</typeparam>
/// <returns>A map of <see cref="Task"/> representing the asynchronous operation for every node.</returns>
- IDictionary<IClusterNode, Task<IJobExecution<TResult>>> SubmitBroadcast<TResult>(
+ IDictionary<IClusterNode, Task<IJobExecution<TResult>>> SubmitBroadcast<TArg, TResult>(
IEnumerable<IClusterNode> nodes,
- JobDescriptor<TResult> jobDescriptor,
- params object?[]? args);
+ JobDescriptor<TArg, TResult> jobDescriptor,
+ TArg arg);
}
diff --git a/modules/platforms/dotnet/Apache.Ignite/Compute/JobDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite/Compute/JobDescriptor.cs
index c0e1a57830..57d0d74127 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Compute/JobDescriptor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Compute/JobDescriptor.cs
@@ -17,7 +17,6 @@
namespace Apache.Ignite.Compute;
-using System;
using System.Collections.Generic;
/// <summary>
@@ -26,14 +25,9 @@ using System.Collections.Generic;
/// <param name="JobClassName">Java class name of the job to execute.</param>
/// <param name="DeploymentUnits">Deployment units.</param>
/// <param name="Options">Options.</param>
+/// <typeparam name="TArg">Argument type.</typeparam>
/// <typeparam name="TResult">Result type.</typeparam>
-public sealed record JobDescriptor<TResult>(
+public sealed record JobDescriptor<TArg, TResult>(
string JobClassName,
IEnumerable<DeploymentUnit>? DeploymentUnits = null,
- JobExecutionOptions? Options = null)
-{
- /// <summary>
- /// Gets the result type of the job.
- /// </summary>
- public Type ResultType => typeof(TResult);
-}
+ JobExecutionOptions? Options = null);
diff --git a/modules/platforms/dotnet/Apache.Ignite/ErrorCodes.g.cs b/modules/platforms/dotnet/Apache.Ignite/ErrorCodes.g.cs
old mode 100755
new mode 100644
index a06831a3f5..a14f60b322
--- a/modules/platforms/dotnet/Apache.Ignite/ErrorCodes.g.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/ErrorCodes.g.cs
@@ -50,6 +50,7 @@ namespace Apache.Ignite
CriticalWorkers.GroupCode => CriticalWorkers.GroupName,
DisasterRecovery.GroupCode => DisasterRecovery.GroupName,
Embedded.GroupCode => Embedded.GroupName,
+ Marshalling.GroupCode => Marshalling.GroupName,
_ => UnknownGroupName
};
@@ -620,5 +621,21 @@ namespace Apache.Ignite
/// <summary> NodeStart error. </summary>
public const int NodeStart = (GroupCode << 16) | (4 & 0xFFFF);
}
+
+ /// <summary> Marshalling errors. </summary>
+ public static class Marshalling
+ {
+ /// <summary> Marshalling group code. </summary>
+ public const short GroupCode = 22;
+
+ /// <summary> Marshalling group name. </summary>
+ public const String GroupName = "MARSHALLING";
+
+ /// <summary> Common error. </summary>
+ public const int Common = (GroupCode << 16) | (1 & 0xFFFF);
+
+ /// <summary> UnsupportedObjectType error. </summary>
+ public const int UnsupportedObjectType = (GroupCode << 16) | (2 & 0xFFFF);
+ }
}
}
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/Compute/Compute.cs b/modules/platforms/dotnet/Apache.Ignite/Internal/Compute/Compute.cs
index 947a88b1d5..bdb85f87fc 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Compute/Compute.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Compute/Compute.cs
@@ -60,10 +60,10 @@ namespace Apache.Ignite.Internal.Compute
}
/// <inheritdoc/>
- public Task<IJobExecution<TResult>> SubmitAsync<TTarget, TResult>(
+ public Task<IJobExecution<TResult>> SubmitAsync<TTarget, TArg, TResult>(
IJobTarget<TTarget> target,
- JobDescriptor<TResult> jobDescriptor,
- params object?[]? args)
+ JobDescriptor<TArg, TResult> jobDescriptor,
+ TArg arg)
where TTarget : notnull
{
IgniteArgumentCheck.NotNull(target);
@@ -71,19 +71,19 @@ namespace Apache.Ignite.Internal.Compute
return target switch
{
- JobTarget.SingleNodeTarget singleNode => SubmitAsync(new[] { singleNode.Data }, jobDescriptor, args),
- JobTarget.AnyNodeTarget anyNode => SubmitAsync(anyNode.Data, jobDescriptor, args),
- JobTarget.ColocatedTarget<TTarget> colocated => SubmitColocatedAsync(colocated, jobDescriptor, args),
+ JobTarget.SingleNodeTarget singleNode => SubmitAsync(new[] { singleNode.Data }, jobDescriptor, arg),
+ JobTarget.AnyNodeTarget anyNode => SubmitAsync(anyNode.Data, jobDescriptor, arg),
+ JobTarget.ColocatedTarget<TTarget> colocated => SubmitColocatedAsync(colocated, jobDescriptor, arg),
_ => throw new ArgumentException("Unsupported job target: " + target)
};
}
/// <inheritdoc/>
- public IDictionary<IClusterNode, Task<IJobExecution<T>>> SubmitBroadcast<T>(
+ public IDictionary<IClusterNode, Task<IJobExecution<TResult>>> SubmitBroadcast<TArg, TResult>(
IEnumerable<IClusterNode> nodes,
- JobDescriptor<T> jobDescriptor,
- params object?[]? args)
+ JobDescriptor<TArg, TResult> jobDescriptor,
+ TArg arg)
{
IgniteArgumentCheck.NotNull(nodes);
IgniteArgumentCheck.NotNull(jobDescriptor);
@@ -92,11 +92,12 @@ namespace Apache.Ignite.Internal.Compute
var options = jobDescriptor.Options ?? JobExecutionOptions.Default;
var units = GetUnitsCollection(jobDescriptor.DeploymentUnits);
- var res = new Dictionary<IClusterNode, Task<IJobExecution<T>>>();
+ var res = new Dictionary<IClusterNode, Task<IJobExecution<TResult>>>();
foreach (var node in nodes)
{
- Task<IJobExecution<T>> task = ExecuteOnNodes<T>(new[] { node }, units, jobDescriptor.JobClassName, options, args);
+ Task<IJobExecution<TResult>> task = ExecuteOnNodes<TArg, TResult>(
+ new[] { node }, units, jobDescriptor.JobClassName, options, arg);
res[node] = task;
}
@@ -282,12 +283,12 @@ namespace Apache.Ignite.Internal.Compute
}
}
- private async Task<IJobExecution<T>> ExecuteOnNodes<T>(
+ private async Task<IJobExecution<TResult>> ExecuteOnNodes<TArg, TResult>(
ICollection<IClusterNode> nodes,
IEnumerable<DeploymentUnit>? units,
string jobClassName,
JobExecutionOptions? options,
- object?[]? args)
+ TArg arg)
{
IClusterNode node = GetRandomNode(nodes);
options ??= JobExecutionOptions.Default;
@@ -299,7 +300,7 @@ namespace Apache.Ignite.Internal.Compute
ClientOp.ComputeExecute, writer, PreferredNode.FromName(node.Name), expectNotifications: true)
.ConfigureAwait(false);
- return GetJobExecution<T>(res, readSchema: false);
+ return GetJobExecution<TResult>(res, readSchema: false);
void Write()
{
@@ -311,7 +312,7 @@ namespace Apache.Ignite.Internal.Compute
w.Write(options.Priority);
w.Write(options.MaxRetries);
- w.WriteObjectCollectionAsBinaryTuple(args);
+ w.WriteObjectAsBinaryTuple(arg);
}
}
@@ -336,12 +337,12 @@ namespace Apache.Ignite.Internal.Compute
}
[SuppressMessage("Maintainability", "CA1508:Avoid dead conditional code", Justification = "False positive")]
- private async Task<IJobExecution<T>> ExecuteColocatedAsync<T, TKey>(
+ private async Task<IJobExecution<TResult>> ExecuteColocatedAsync<TArg, TResult, TKey>(
string tableName,
TKey key,
Func<Table, IRecordSerializerHandler<TKey>> serializerHandlerFunc,
- JobDescriptor<T> descriptor,
- params object?[]? args)
+ JobDescriptor<TArg, TResult> descriptor,
+ TArg arg)
where TKey : notnull
{
var options = descriptor.Options ?? JobExecutionOptions.Default;
@@ -364,7 +365,7 @@ namespace Apache.Ignite.Internal.Compute
ClientOp.ComputeExecuteColocated, bufferWriter, preferredNode, expectNotifications: true)
.ConfigureAwait(false);
- return GetJobExecution<T>(res, readSchema: true);
+ return GetJobExecution<TResult>(res, readSchema: true);
}
catch (IgniteException e) when (e.Code == ErrorGroups.Client.TableIdNotFound)
{
@@ -400,16 +401,16 @@ namespace Apache.Ignite.Internal.Compute
w.Write(options.Priority);
w.Write(options.MaxRetries);
- w.WriteObjectCollectionAsBinaryTuple(args);
+ w.WriteObjectAsBinaryTuple(arg);
return colocationHash;
}
}
- private async Task<IJobExecution<T>> SubmitAsync<T>(
+ private async Task<IJobExecution<TResult>> SubmitAsync<TArg, TResult>(
IEnumerable<IClusterNode> nodes,
- JobDescriptor<T> jobDescriptor,
- params object?[]? args)
+ JobDescriptor<TArg, TResult> jobDescriptor,
+ TArg arg)
{
IgniteArgumentCheck.NotNull(nodes);
IgniteArgumentCheck.NotNull(jobDescriptor);
@@ -418,39 +419,39 @@ namespace Apache.Ignite.Internal.Compute
var nodesCol = GetNodesCollection(nodes);
IgniteArgumentCheck.Ensure(nodesCol.Count > 0, nameof(nodes), "Nodes can't be empty.");
- return await ExecuteOnNodes<T>(
+ return await ExecuteOnNodes<TArg, TResult>(
nodesCol,
jobDescriptor.DeploymentUnits,
jobDescriptor.JobClassName,
jobDescriptor.Options,
- args).ConfigureAwait(false);
+ arg).ConfigureAwait(false);
}
- private async Task<IJobExecution<T>> SubmitColocatedAsync<T, TKey>(
+ private async Task<IJobExecution<TResult>> SubmitColocatedAsync<TArg, TResult, TKey>(
JobTarget.ColocatedTarget<TKey> target,
- JobDescriptor<T> jobDescriptor,
- params object?[]? args)
+ JobDescriptor<TArg, TResult> jobDescriptor,
+ TArg arg)
where TKey : notnull
{
IgniteArgumentCheck.NotNull(jobDescriptor);
if (target.Data is IIgniteTuple tuple)
{
- return await ExecuteColocatedAsync<T, IIgniteTuple>(
+ return await ExecuteColocatedAsync<TArg, TResult, IIgniteTuple>(
target.TableName,
tuple,
static _ => TupleSerializerHandler.Instance,
jobDescriptor,
- args)
+ arg)
.ConfigureAwait(false);
}
- return await ExecuteColocatedAsync<T, TKey>(
+ return await ExecuteColocatedAsync<TArg, TResult, TKey>(
target.TableName,
target.Data,
static table => table.GetRecordViewInternal<TKey>().RecordSerializer.Handler,
jobDescriptor,
- args)
+ arg)
.ConfigureAwait(false);
}
}
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/Proto/MsgPack/MsgPackWriter.cs b/modules/platforms/dotnet/Apache.Ignite/Internal/Proto/MsgPack/MsgPackWriter.cs
index f8bb8d07c4..888980de9d 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Proto/MsgPack/MsgPackWriter.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Proto/MsgPack/MsgPackWriter.cs
@@ -356,6 +356,24 @@ internal readonly ref struct MsgPackWriter
}
}
+ /// <summary>
+ /// Writes an object with type code.
+ /// </summary>
+ /// <param name="obj">Object.</param>
+ public void WriteObjectAsBinaryTuple(object? obj)
+ {
+ if (obj == null)
+ {
+ WriteNil();
+
+ return;
+ }
+
+ using var builder = new BinaryTupleBuilder(3);
+ builder.AppendObjectWithType(obj);
+ Write(builder.Build().Span);
+ }
+
/// <summary>
/// Writes an array of objects with type codes.
/// </summary>
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamerWithReceiver.cs b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamerWithReceiver.cs
index 3dbc64269d..ef08db55ca 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamerWithReceiver.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/DataStreamerWithReceiver.cs
@@ -63,14 +63,15 @@ internal static class DataStreamerWithReceiver
/// <param name="resultChannel">Channel for results from the receiver. Null when results are not expected.</param>
/// <param name="units">Deployment units. Can be empty.</param>
/// <param name="receiverClassName">Java class name of the streamer receiver to execute on the server.</param>
- /// <param name="receiverArgs">Receiver args.</param>
+ /// <param name="receiverArg">Receiver arg.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <typeparam name="TSource">Source type.</typeparam>
/// <typeparam name="TKey">Key type.</typeparam>
/// <typeparam name="TPayload">Payload type.</typeparam>
+ /// <typeparam name="TArg">Arg type.</typeparam>
/// <typeparam name="TResult">Result type.</typeparam>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
- internal static async Task StreamDataAsync<TSource, TKey, TPayload, TResult>(
+ internal static async Task StreamDataAsync<TSource, TKey, TPayload, TArg, TResult>(
IAsyncEnumerable<TSource> data,
Table table,
Func<TSource, TKey> keySelector,
@@ -80,7 +81,7 @@ internal static class DataStreamerWithReceiver
Channel<TResult>? resultChannel,
IEnumerable<DeploymentUnit> units,
string receiverClassName,
- ICollection<object>? receiverArgs,
+ TArg receiverArg,
CancellationToken cancellationToken)
where TKey : notnull
where TPayload : notnull
@@ -327,26 +328,21 @@ internal static class DataStreamerWithReceiver
var expectResults = resultChannel != null;
w.Write(expectResults);
- WriteReceiverPayload(ref w, receiverClassName, receiverArgs ?? Array.Empty<object>(), items);
+ WriteReceiverPayload(ref w, receiverClassName, receiverArg, items);
}
}
- private static void WriteReceiverPayload<T>(ref MsgPackWriter w, string className, ICollection<object> args, Span<T> items)
+ private static void WriteReceiverPayload<T>(ref MsgPackWriter w, string className, object? arg, Span<T> items)
{
Debug.Assert(items.Length > 0, "items.Length > 0");
Debug.Assert(!items.IsEmpty, "!items.IsEmpty");
- // className + args size + args + items size + item type + items.
- int binaryTupleSize = 1 + 1 + args.Count * 3 + 1 + 1 + items.Length;
+ // className + arg + items size + item type + items.
+ int binaryTupleSize = 1 + 3 + 1 + 1 + items.Length;
using var builder = new BinaryTupleBuilder(binaryTupleSize);
builder.AppendString(className);
- builder.AppendInt(args.Count);
-
- foreach (var arg in args)
- {
- builder.AppendObjectWithType(arg);
- }
+ builder.AppendObjectWithType(arg);
builder.AppendObjectCollectionWithType(items);
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/KeyValueView.cs b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/KeyValueView.cs
index 30f5da1c97..058aebc1cb 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/KeyValueView.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/KeyValueView.cs
@@ -164,12 +164,12 @@ internal sealed class KeyValueView<TK, TV> : IKeyValueView<TK, TV>
await _recordView.StreamDataAsync(ToKv(data), options, cancellationToken).ConfigureAwait(false);
/// <inheritdoc/>
- public IAsyncEnumerable<TResult> StreamDataAsync<TSource, TPayload, TResult>(
+ public IAsyncEnumerable<TResult> StreamDataAsync<TSource, TPayload, TArg, TResult>(
IAsyncEnumerable<TSource> data,
Func<TSource, KeyValuePair<TK, TV>> keySelector,
Func<TSource, TPayload> payloadSelector,
- ReceiverDescriptor<TResult> receiver,
- ICollection<object>? receiverArgs,
+ ReceiverDescriptor<TArg, TResult> receiver,
+ TArg receiverArg,
DataStreamerOptions? options,
CancellationToken cancellationToken = default)
where TPayload : notnull =>
@@ -178,17 +178,17 @@ internal sealed class KeyValueView<TK, TV> : IKeyValueView<TK, TV>
src => ToKv(keySelector(src)),
payloadSelector,
receiver,
- receiverArgs,
+ receiverArg,
options,
cancellationToken);
/// <inheritdoc/>
- public Task StreamDataAsync<TSource, TPayload>(
+ public Task StreamDataAsync<TSource, TPayload, TArg>(
IAsyncEnumerable<TSource> data,
Func<TSource, KeyValuePair<TK, TV>> keySelector,
Func<TSource, TPayload> payloadSelector,
- ReceiverDescriptor receiver,
- ICollection<object>? receiverArgs,
+ ReceiverDescriptor<TArg> receiver,
+ TArg receiverArg,
DataStreamerOptions? options,
CancellationToken cancellationToken = default)
where TPayload : notnull =>
@@ -197,7 +197,7 @@ internal sealed class KeyValueView<TK, TV> : IKeyValueView<TK, TV>
src => ToKv(keySelector(src)),
payloadSelector,
receiver,
- receiverArgs,
+ receiverArg,
options,
cancellationToken);
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/RecordView.cs b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/RecordView.cs
index 518da6ee88..04d1c71d12 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Table/RecordView.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Table/RecordView.cs
@@ -308,12 +308,12 @@ namespace Apache.Ignite.Internal.Table
cancellationToken).ConfigureAwait(false);
/// <inheritdoc/>
- public async IAsyncEnumerable<TResult> StreamDataAsync<TSource, TPayload, TResult>(
+ public async IAsyncEnumerable<TResult> StreamDataAsync<TSource, TPayload, TArg, TResult>(
IAsyncEnumerable<TSource> data,
Func<TSource, T> keySelector,
Func<TSource, TPayload> payloadSelector,
- ReceiverDescriptor<TResult> receiver,
- ICollection<object>? receiverArgs,
+ ReceiverDescriptor<TArg, TResult> receiver,
+ TArg receiverArg,
DataStreamerOptions? options,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
where TPayload : notnull
@@ -381,7 +381,7 @@ namespace Apache.Ignite.Internal.Table
resultChannel,
receiver.DeploymentUnits ?? Array.Empty<DeploymentUnit>(),
receiver.ReceiverClassName,
- receiverArgs,
+ receiverArg,
cancellationToken).ConfigureAwait(false);
resultChannel.Writer.Complete();
@@ -394,17 +394,17 @@ namespace Apache.Ignite.Internal.Table
}
/// <inheritdoc/>
- public async Task StreamDataAsync<TSource, TPayload>(
+ public async Task StreamDataAsync<TSource, TPayload, TArg>(
IAsyncEnumerable<TSource> data,
Func<TSource, T> keySelector,
Func<TSource, TPayload> payloadSelector,
- ReceiverDescriptor receiver,
- ICollection<object>? receiverArgs,
+ ReceiverDescriptor<TArg> receiver,
+ TArg receiverArg,
DataStreamerOptions? options,
CancellationToken cancellationToken = default)
where TPayload : notnull
{
- await DataStreamerWithReceiver.StreamDataAsync<TSource, T, TPayload, object>(
+ await DataStreamerWithReceiver.StreamDataAsync<TSource, T, TPayload, TArg, object>(
data,
_table,
keySelector,
@@ -414,7 +414,7 @@ namespace Apache.Ignite.Internal.Table
resultChannel: null,
receiver.DeploymentUnits ?? Array.Empty<DeploymentUnit>(),
receiver.ReceiverClassName,
- receiverArgs,
+ receiverArg,
cancellationToken).ConfigureAwait(false);
}
diff --git a/modules/platforms/dotnet/Apache.Ignite/Table/IDataStreamerTarget.cs b/modules/platforms/dotnet/Apache.Ignite/Table/IDataStreamerTarget.cs
index 0612dfc3f4..a29231ae33 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Table/IDataStreamerTarget.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Table/IDataStreamerTarget.cs
@@ -74,7 +74,7 @@ public interface IDataStreamerTarget<T>
/// <param name="keySelector">Key selector.</param>
/// <param name="payloadSelector">Payload selector.</param>
/// <param name="receiver">Streamer receiver descriptor.</param>
- /// <param name="receiverArgs">Receiver args.</param>
+ /// <param name="receiverArg">Receiver argument.</param>
/// <param name="options">Streamer options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>
@@ -85,13 +85,14 @@ public interface IDataStreamerTarget<T>
/// </returns>
/// <typeparam name="TSource">Source item type.</typeparam>
/// <typeparam name="TPayload">Payload type.</typeparam>
+ /// <typeparam name="TArg">Argument type.</typeparam>
/// <typeparam name="TResult">Result type.</typeparam>
- IAsyncEnumerable<TResult> StreamDataAsync<TSource, TPayload, TResult>(
+ IAsyncEnumerable<TResult> StreamDataAsync<TSource, TPayload, TArg, TResult>(
IAsyncEnumerable<TSource> data,
Func<TSource, T> keySelector,
Func<TSource, TPayload> payloadSelector,
- ReceiverDescriptor<TResult> receiver,
- ICollection<object>? receiverArgs = null,
+ ReceiverDescriptor<TArg, TResult> receiver,
+ TArg receiverArg,
DataStreamerOptions? options = null,
CancellationToken cancellationToken = default)
where TPayload : notnull;
@@ -103,18 +104,19 @@ public interface IDataStreamerTarget<T>
/// <param name="keySelector">Key selector.</param>
/// <param name="payloadSelector">Payload selector.</param>
/// <param name="receiver">Receiver descriptor.</param>
- /// <param name="receiverArgs">Receiver args.</param>
+ /// <param name="receiverArg">Receiver arg.</param>
/// <param name="options">Streamer options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
/// <typeparam name="TSource">Source item type.</typeparam>
/// <typeparam name="TPayload">Payload type.</typeparam>
- Task StreamDataAsync<TSource, TPayload>(
+ /// <typeparam name="TArg">Argument type.</typeparam>
+ Task StreamDataAsync<TSource, TPayload, TArg>(
IAsyncEnumerable<TSource> data,
Func<TSource, T> keySelector,
Func<TSource, TPayload> payloadSelector,
- ReceiverDescriptor receiver,
- ICollection<object>? receiverArgs = null,
+ ReceiverDescriptor<TArg> receiver,
+ TArg receiverArg,
DataStreamerOptions? options = null,
CancellationToken cancellationToken = default)
where TPayload : notnull;
diff --git a/modules/platforms/dotnet/Apache.Ignite/Table/ReceiverDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite/Table/ReceiverDescriptor.cs
index 2b9afb8c68..0eb46af168 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Table/ReceiverDescriptor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Table/ReceiverDescriptor.cs
@@ -17,7 +17,6 @@
namespace Apache.Ignite.Table;
-using System;
using System.Collections.Generic;
using Compute;
@@ -26,7 +25,8 @@ using Compute;
/// </summary>
/// <param name="ReceiverClassName">Java class name of the streamer receiver to execute.</param>
/// <param name="DeploymentUnits">Deployment units.</param>
-public sealed record ReceiverDescriptor(
+/// <typeparam name="TArg">Argument type.</typeparam>
+public sealed record ReceiverDescriptor<TArg>(
string ReceiverClassName,
IEnumerable<DeploymentUnit>? DeploymentUnits = null);
@@ -35,13 +35,8 @@ public sealed record ReceiverDescriptor(
/// </summary>
/// <param name="ReceiverClassName">Java class name of the streamer receiver to execute.</param>
/// <param name="DeploymentUnits">Deployment units.</param>
+/// <typeparam name="TArg">Argument type.</typeparam>
/// <typeparam name="TResult">Result type.</typeparam>
-public sealed record ReceiverDescriptor<TResult>(
+public sealed record ReceiverDescriptor<TArg, TResult>(
string ReceiverClassName,
- IEnumerable<DeploymentUnit>? DeploymentUnits = null)
-{
- /// <summary>
- /// Gets the result type.
- /// </summary>
- public Type ResultType => typeof(TResult);
-}
+ IEnumerable<DeploymentUnit>? DeploymentUnits = null);
diff --git a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/compute/ItComputeControllerTest.java b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/compute/ItComputeControllerTest.java
index 257578bb56..0fdd920b55 100644
--- a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/compute/ItComputeControllerTest.java
+++ b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/compute/ItComputeControllerTest.java
@@ -366,7 +366,7 @@ public class ItComputeControllerTest extends ClusterPerClassIntegrationTest {
}
private static JobExecution<String> runBlockingJob(IgniteImpl entryNode, Set<ClusterNode> nodes) {
- return entryNode.compute().submit(JobTarget.anyNode(nodes), JobDescriptor.builder(BlockingJob.class).build());
+ return entryNode.compute().submit(JobTarget.anyNode(nodes), JobDescriptor.builder(BlockingJob.class).build(), null);
}
private static void unblockJob() {
@@ -395,10 +395,10 @@ public class ItComputeControllerTest extends ClusterPerClassIntegrationTest {
client.toBlocking().exchange(DELETE("/jobs/" + jobId));
}
- private static class BlockingJob implements ComputeJob<String> {
+ private static class BlockingJob implements ComputeJob<Void, String> {
/** {@inheritDoc} */
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Void args) {
synchronized (LOCK) {
try {
LOCK.wait();
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/PlatformTestNodeRunner.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/PlatformTestNodeRunner.java
index 2e77c782b6..95bcc56adc 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/PlatformTestNodeRunner.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/PlatformTestNodeRunner.java
@@ -552,11 +552,9 @@ public class PlatformTestNodeRunner {
* Compute job that creates a table.
*/
@SuppressWarnings("unused") // Used by platform tests.
- private static class CreateTableJob implements ComputeJob<String> {
+ private static class CreateTableJob implements ComputeJob<String, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
- String tableName = (String) args[0];
-
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, String tableName) {
context.ignite().sql().execute(null, "CREATE TABLE " + tableName + "(key BIGINT PRIMARY KEY, val INT)");
return completedFuture(tableName);
@@ -567,10 +565,9 @@ public class PlatformTestNodeRunner {
* Compute job that drops a table.
*/
@SuppressWarnings("unused") // Used by platform tests.
- private static class DropTableJob implements ComputeJob<String> {
+ private static class DropTableJob implements ComputeJob<String, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
- String tableName = (String) args[0];
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, String tableName) {
context.ignite().sql().execute(null, "DROP TABLE " + tableName + "");
return completedFuture(tableName);
@@ -581,10 +578,10 @@ public class PlatformTestNodeRunner {
* Compute job that throws an exception.
*/
@SuppressWarnings("unused") // Used by platform tests.
- private static class ExceptionJob implements ComputeJob<String> {
+ private static class ExceptionJob implements ComputeJob<String, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
- throw new RuntimeException("Test exception: " + args[0]);
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, String msg) {
+ throw new RuntimeException("Test exception: " + msg);
}
}
@@ -592,10 +589,10 @@ public class PlatformTestNodeRunner {
* Compute job that throws an exception.
*/
@SuppressWarnings("unused") // Used by platform tests.
- private static class CheckedExceptionJob implements ComputeJob<String> {
+ private static class CheckedExceptionJob implements ComputeJob<String, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
- throw new CompletionException(new IgniteCheckedException(Common.NODE_LEFT_ERR, "TestCheckedEx: " + args[0]));
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, String msg) {
+ throw new CompletionException(new IgniteCheckedException(Common.NODE_LEFT_ERR, "TestCheckedEx: " + msg));
}
}
@@ -603,13 +600,14 @@ public class PlatformTestNodeRunner {
* Compute job that computes row colocation hash.
*/
@SuppressWarnings("unused") // Used by platform tests.
- private static class ColocationHashJob implements ComputeJob<Integer> {
+ private static class ColocationHashJob implements ComputeJob<byte[], Integer> {
@Override
- public CompletableFuture<Integer> executeAsync(JobExecutionContext context, Object... args) {
- var columnCount = (int) args[0];
- var buf = (byte[]) args[1];
- var timePrecision = (int) args[2];
- var timestampPrecision = (int) args[3];
+ public CompletableFuture<Integer> executeAsync(JobExecutionContext context, byte[] args) {
+ BinaryTupleReader argsReader = new BinaryTupleReader(4, args);
+ var columnCount = argsReader.intValue(0);
+ var timePrecision = argsReader.intValue(1);
+ var timestampPrecision = argsReader.intValue(2);
+ var buf = argsReader.bytesValue(3);
List<Column> columns = new ArrayList<>(columnCount);
var tuple = Tuple.create(columnCount);
@@ -723,11 +721,12 @@ public class PlatformTestNodeRunner {
* Compute job that computes row colocation hash according to the current table schema.
*/
@SuppressWarnings("unused") // Used by platform tests.
- private static class TableRowColocationHashJob implements ComputeJob<Integer> {
+ private static class TableRowColocationHashJob implements ComputeJob<byte[], Integer> {
@Override
- public CompletableFuture<Integer> executeAsync(JobExecutionContext context, Object... args) {
- String tableName = (String) args[0];
- int i = (int) args[1];
+ public CompletableFuture<Integer> executeAsync(JobExecutionContext context, byte[] args) {
+ BinaryTupleReader reader = new BinaryTupleReader(2, args);
+ String tableName = reader.stringValue(0);
+ int i = reader.intValue(1);
Tuple key = Tuple.create().set("id", 1 + i).set("id0", 2L + i).set("id1", "3" + i);
@SuppressWarnings("resource")
@@ -743,10 +742,10 @@ public class PlatformTestNodeRunner {
* Compute job that enables or disables client authentication.
*/
@SuppressWarnings("unused") // Used by platform tests.
- private static class EnableAuthenticationJob implements ComputeJob<Void> {
+ private static class EnableAuthenticationJob implements ComputeJob<Integer, Void> {
@Override
- public CompletableFuture<Void> executeAsync(JobExecutionContext context, Object... args) {
- boolean enable = ((Integer) args[0]) != 0;
+ public CompletableFuture<Void> executeAsync(JobExecutionContext context, Integer flag) {
+ boolean enable = flag != 0;
@SuppressWarnings("resource") IgniteImpl ignite = (IgniteImpl) context.ignite();
CompletableFuture<Void> changeFuture = ignite.clusterConfiguration().change(
@@ -772,13 +771,14 @@ public class PlatformTestNodeRunner {
}
@SuppressWarnings("unused") // Used by platform tests.
- private static class TestReceiver implements DataStreamerReceiver<String, String> {
+ private static class TestReceiver implements DataStreamerReceiver<String, String, String> {
@SuppressWarnings("resource")
@Override
- public @Nullable CompletableFuture<List<String>> receive(List<String> page, DataStreamerReceiverContext ctx, Object... args) {
- String tableName = (String) args[0];
- String arg1 = (String) args[1];
- int arg2 = (Integer) args[2];
+ public @Nullable CompletableFuture<List<String>> receive(List<String> page, DataStreamerReceiverContext ctx, String arg) {
+ String[] args = arg.split(":", 3);
+ String tableName = args[0];
+ String arg1 = args[1];
+ int arg2 = Integer.parseInt(args[2]);
if (Objects.equals(arg1, "throw")) {
throw new ArithmeticException("Test exception: " + arg2);
@@ -801,18 +801,20 @@ public class PlatformTestNodeRunner {
recordView.upsert(null, rec);
}
- return CompletableFuture.completedFuture(res);
+ return completedFuture(res);
}
}
@SuppressWarnings("unused") // Used by platform tests.
- private static class UpsertElementTypeNameReceiver implements DataStreamerReceiver<Object, Object> {
+ private static class UpsertElementTypeNameReceiver implements DataStreamerReceiver<Object, String, Object> {
@SuppressWarnings("resource")
@Override
- public @Nullable CompletableFuture<List<Object>> receive(List<Object> page, DataStreamerReceiverContext ctx, Object... args) {
- String tableName = (String) args[0];
- long id1 = (Long) args[1];
- long id2 = (Long) args[2];
+ public @Nullable CompletableFuture<List<Object>> receive(List<Object> page, DataStreamerReceiverContext ctx, String arg) {
+ String[] args = arg.split(":", 3);
+
+ String tableName = args[0];
+ long id1 = Long.parseLong(args[1]);
+ long id2 = Long.parseLong(args[2]);
Table table = ctx.ignite().tables().table(tableName);
RecordView<Tuple> recordView = table.recordView();
@@ -836,17 +838,17 @@ public class PlatformTestNodeRunner {
}
@SuppressWarnings("unused") // Used by platform tests.
- private static class EchoArgsReceiver implements DataStreamerReceiver<Object, Object> {
+ private static class EchoArgsReceiver implements DataStreamerReceiver<Object, Object, Object> {
@Override
- public CompletableFuture<List<Object>> receive(List<Object> page, DataStreamerReceiverContext ctx, Object... args) {
- return CompletableFuture.completedFuture(List.of(args));
+ public CompletableFuture<List<Object>> receive(List<Object> page, DataStreamerReceiverContext ctx, Object arg) {
+ return CompletableFuture.completedFuture(List.of(arg));
}
}
@SuppressWarnings("unused") // Used by platform tests.
- private static class EchoReceiver implements DataStreamerReceiver<Object, Object> {
+ private static class EchoReceiver implements DataStreamerReceiver<Object, Object, Object> {
@Override
- public CompletableFuture<List<Object>> receive(List<Object> page, DataStreamerReceiverContext ctx, Object... args) {
+ public CompletableFuture<List<Object>> receive(List<Object> page, DataStreamerReceiverContext ctx, Object arg) {
return CompletableFuture.completedFuture(page);
}
}
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientComputeMarshallingTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientComputeMarshallingTest.java
new file mode 100644
index 0000000000..d4dd69c1f2
--- /dev/null
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientComputeMarshallingTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.runner.app.client;
+
+import static java.util.concurrent.CompletableFuture.completedFuture;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.client.IgniteClient;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.IgniteCompute;
+import org.apache.ignite.compute.JobDescriptor;
+import org.apache.ignite.compute.JobExecutionContext;
+import org.apache.ignite.compute.JobTarget;
+import org.apache.ignite.marshaling.ByteArrayMarshaler;
+import org.apache.ignite.marshaling.Marshaler;
+import org.apache.ignite.network.ClusterNode;
+import org.jetbrains.annotations.Nullable;
+import org.junit.jupiter.api.Test;
+
+/**
+ * TBD.
+ */
+@SuppressWarnings("resource")
+public class ItThinClientComputeMarshallingTest extends ItAbstractThinClientTest {
+ @Test
+ void testClusterNodes() {
+ List<ClusterNode> nodes = sortedNodes();
+
+ assertEquals(2, nodes.size());
+
+ assertEquals("itccmt_n_3344", nodes.get(0).name());
+ assertEquals(3344, nodes.get(0).address().port());
+ assertTrue(nodes.get(0).id().length() > 10);
+
+ assertEquals("itccmt_n_3345", nodes.get(1).name());
+ assertEquals(3345, nodes.get(1).address().port());
+ assertTrue(nodes.get(1).id().length() > 10);
+ }
+
+ @Test
+ void customArgMarshaller() {
+ // Given entry node that are not supposed to execute job.
+ var node = server(0);
+ // And another target node.
+ var targetNode = node(1);
+
+ // When run job with custom marshaller for string argument.
+ var compute = computeClientOn(node);
+ String result = compute.execute(
+ JobTarget.node(targetNode),
+ JobDescriptor.builder(ArgMarshalingJob.class)
+ .argumentMarshaller(new ArgumentStringMarshaller())
+ .build(),
+ "Input"
+ );
+
+ // Then both client and server marshaler were called.
+ assertEquals("Input:marshalledOnClient:unmarshalledOnServer", result);
+ }
+
+ private IgniteCompute computeClientOn(Ignite node) {
+ return IgniteClient.builder()
+ .addresses(getClientAddresses(List.of(node)).toArray(new String[0]))
+ .build()
+ .compute();
+ }
+
+ static class ArgumentStringMarshaller implements ByteArrayMarshaler<String> {
+ @Override
+ public byte @Nullable [] marshal(@Nullable String object) {
+ return ByteArrayMarshaler.super.marshal(object + ":marshalledOnClient");
+ }
+ }
+
+ static class ArgMarshalingJob implements ComputeJob<String, String> {
+ @Override
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, @Nullable String arg) {
+ return completedFuture(arg);
+ }
+
+ @Override
+ public Marshaler<String, byte[]> inputMarshaler() {
+ return new ByteArrayMarshaler<>() {
+ @Override
+ public String unmarshal(byte @Nullable [] raw) {
+ return ByteArrayMarshaler.super.unmarshal(raw) + ":unmarshalledOnServer";
+ }
+ };
+ }
+ }
+
+ static class ResultMarshalingJob implements ComputeJob<String, String> {
+
+ @Override
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, @Nullable String arg) {
+ return completedFuture(arg + ":processedOnServer");
+ }
+
+ @Override
+ public Marshaler<String, byte[]> resultMarshaler() {
+ return new ByteArrayMarshaler<>() {
+ @Override
+ public byte @Nullable [] marshal(@Nullable String object) {
+ return ByteArrayMarshaler.super.marshal(object + ":marshalledOnServer");
+ }
+ };
+ }
+ }
+
+ private ClusterNode node(int idx) {
+ return sortedNodes().get(idx);
+ }
+
+ private List<ClusterNode> sortedNodes() {
+ return client().clusterNodes().stream()
+ .sorted(Comparator.comparing(ClusterNode::name))
+ .collect(Collectors.toList());
+ }
+}
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientComputeTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientComputeTest.java
index a12855827d..e6bf5a88e4 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientComputeTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientComputeTest.java
@@ -94,6 +94,7 @@ import org.apache.ignite.table.mapper.Mapper;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.Nullable;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
@@ -124,8 +125,12 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
@Test
void testExecuteOnSpecificNode() {
- String res1 = client().compute().execute(JobTarget.node(node(0)), JobDescriptor.builder(NodeNameJob.class).build());
- String res2 = client().compute().execute(JobTarget.node(node(1)), JobDescriptor.builder(NodeNameJob.class).build());
+ String res1 = client().compute().execute(
+ JobTarget.node(node(0)), JobDescriptor.builder(NodeNameJob.class).build(), null
+ );
+ String res2 = client().compute().execute(
+ JobTarget.node(node(1)), JobDescriptor.builder(NodeNameJob.class).build(), null
+ );
assertEquals("itcct_n_3344", res1);
assertEquals("itcct_n_3345", res2);
@@ -134,10 +139,11 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
@Test
void testExecuteOnSpecificNodeAsync() {
JobExecution<String> execution1 = client().compute().submit(
- JobTarget.node(node(0)), JobDescriptor.builder(NodeNameJob.class).build());
-
+ JobTarget.node(node(0)), JobDescriptor.builder(NodeNameJob.class).build(), null
+ );
JobExecution<String> execution2 = client().compute().submit(
- JobTarget.node(node(1)), JobDescriptor.builder(NodeNameJob.class).build());
+ JobTarget.node(node(1)), JobDescriptor.builder(NodeNameJob.class).build(), null
+ );
assertThat(execution1.resultAsync(), willBe("itcct_n_3344"));
assertThat(execution2.resultAsync(), willBe("itcct_n_3345"));
@@ -150,7 +156,8 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
void testCancellingCompletedJob() {
JobExecution<String> execution = client().compute().submit(
JobTarget.node(node(0)),
- JobDescriptor.builder(NodeNameJob.class).build());
+ JobDescriptor.builder(NodeNameJob.class).build(), null
+ );
assertThat(execution.resultAsync(), willBe("itcct_n_3344"));
@@ -163,7 +170,8 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
void testChangingPriorityCompletedJob() {
JobExecution<String> execution = client().compute().submit(
JobTarget.node(node(0)),
- JobDescriptor.builder(NodeNameJob.class).build());
+ JobDescriptor.builder(NodeNameJob.class).build(), null
+ );
assertThat(execution.resultAsync(), willBe("itcct_n_3344"));
@@ -233,7 +241,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
@Test
void testExecuteOnRandomNode() {
- String res = client().compute().execute(JobTarget.anyNode(sortedNodes()), JobDescriptor.builder(NodeNameJob.class).build());
+ String res = client().compute().execute(JobTarget.anyNode(sortedNodes()), JobDescriptor.builder(NodeNameJob.class).build(), null);
assertTrue(Set.of("itcct_n_3344", "itcct_n_3345").contains(res));
}
@@ -241,7 +249,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
@Test
void testExecuteOnRandomNodeAsync() {
JobExecution<String> execution = client().compute().submit(
- JobTarget.anyNode(sortedNodes()), JobDescriptor.builder(NodeNameJob.class).build());
+ JobTarget.anyNode(sortedNodes()), JobDescriptor.builder(NodeNameJob.class).build(), null);
assertThat(
execution.resultAsync(),
@@ -255,14 +263,13 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
Map<ClusterNode, JobExecution<String>> executionsPerNode = client().compute().submitBroadcast(
Set.of(node(1)),
JobDescriptor.builder(NodeNameJob.class).build(),
- "_",
- 123);
+ null);
assertEquals(1, executionsPerNode.size());
JobExecution<String> execution = executionsPerNode.get(node(1));
- assertThat(execution.resultAsync(), willBe("itcct_n_3345__123"));
+ assertThat(execution.resultAsync(), willBe("itcct_n_3345"));
assertThat(execution.stateAsync(), willBe(jobStateWithStatus(COMPLETED)));
}
@@ -271,16 +278,16 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
Map<ClusterNode, JobExecution<String>> executionsPerNode = client().compute().submitBroadcast(
new HashSet<>(sortedNodes()),
JobDescriptor.builder(NodeNameJob.class).build(),
- "_",
- 123);
+ null
+ );
assertEquals(2, executionsPerNode.size());
JobExecution<String> execution1 = executionsPerNode.get(node(0));
JobExecution<String> execution2 = executionsPerNode.get(node(1));
- assertThat(execution1.resultAsync(), willBe("itcct_n_3344__123"));
- assertThat(execution2.resultAsync(), willBe("itcct_n_3345__123"));
+ assertThat(execution1.resultAsync(), willBe("itcct_n_3344"));
+ assertThat(execution2.resultAsync(), willBe("itcct_n_3345"));
assertThat(execution1.stateAsync(), willBe(jobStateWithStatus(COMPLETED)));
assertThat(execution2.stateAsync(), willBe(jobStateWithStatus(COMPLETED)));
@@ -289,15 +296,15 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
@Test
void testCancelBroadcastAllNodes() {
int sleepMs = 1_000_000;
- Map<ClusterNode, JobExecution<String>> executionsPerNode = client().compute().submitBroadcast(
+ Map<ClusterNode, JobExecution<Void>> executionsPerNode = client().compute().submitBroadcast(
new HashSet<>(sortedNodes()),
JobDescriptor.builder(SleepJob.class).build(),
sleepMs);
assertEquals(2, executionsPerNode.size());
- JobExecution<String> execution1 = executionsPerNode.get(node(0));
- JobExecution<String> execution2 = executionsPerNode.get(node(1));
+ JobExecution<Void> execution1 = executionsPerNode.get(node(0));
+ JobExecution<Void> execution2 = executionsPerNode.get(node(1));
await().until(execution1::stateAsync, willBe(jobStateWithStatus(EXECUTING)));
await().until(execution2::stateAsync, willBe(jobStateWithStatus(EXECUTING)));
@@ -312,7 +319,9 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
@Test
void testExecuteWithArgs() {
JobExecution<String> execution = client().compute().submit(
- JobTarget.anyNode(client().clusterNodes()), JobDescriptor.builder(ConcatJob.class).build(), 1, "2", 3.3);
+ JobTarget.anyNode(client().clusterNodes()), JobDescriptor.builder(ConcatJob.class).build(),
+ "1:2:3.3"
+ );
assertThat(execution.resultAsync(), willBe("1_2_3.3"));
assertThat(execution.stateAsync(), willBe(jobStateWithStatus(COMPLETED)));
@@ -321,7 +330,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
@Test
void testIgniteExceptionInJobPropagatesToClientWithMessageAndCodeAndTraceIdAsync() {
IgniteException cause = getExceptionInJobExecutionAsync(
- client().compute().submit(JobTarget.node(node(0)), JobDescriptor.builder(IgniteExceptionJob.class).build())
+ client().compute().submit(JobTarget.node(node(0)), JobDescriptor.builder(IgniteExceptionJob.class).build(), null)
);
assertThat(cause.getMessage(), containsString("Custom job error"));
@@ -334,7 +343,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
@Test
void testIgniteExceptionInJobPropagatesToClientWithMessageAndCodeAndTraceIdSync() {
IgniteException cause = getExceptionInJobExecutionSync(
- () -> client().compute().execute(JobTarget.node(node(0)), JobDescriptor.builder(IgniteExceptionJob.class).build())
+ () -> client().compute().execute(JobTarget.node(node(0)), JobDescriptor.builder(IgniteExceptionJob.class).build(), null)
);
assertThat(cause.getMessage(), containsString("Custom job error"));
@@ -368,8 +377,9 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
void testExceptionInJobWithSendServerExceptionStackTraceToClientPropagatesToClientWithStackTraceAsync() {
// Second node has sendServerExceptionStackTraceToClient enabled.
IgniteException cause = getExceptionInJobExecutionAsync(
- client().compute().submit(JobTarget.node(node(1)), JobDescriptor.builder(ExceptionJob.class)
- .build())
+ client().compute().submit(
+ JobTarget.node(node(1)), JobDescriptor.builder(ExceptionJob.class).build(), null
+ )
);
assertComputeExceptionWithStackTrace(cause);
@@ -379,7 +389,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
void testExceptionInJobWithSendServerExceptionStackTraceToClientPropagatesToClientWithStackTraceSync() {
// Second node has sendServerExceptionStackTraceToClient enabled.
IgniteException cause = getExceptionInJobExecutionSync(
- () -> client().compute().execute(JobTarget.node(node(1)), JobDescriptor.builder(ExceptionJob.class).build())
+ () -> client().compute().execute(JobTarget.node(node(1)), JobDescriptor.builder(ExceptionJob.class).build(), null)
);
assertComputeExceptionWithStackTrace(cause);
@@ -389,7 +399,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
void testExceptionInBroadcastJobPropagatesToClient() {
Map<ClusterNode, JobExecution<String>> executions = client().compute().submitBroadcast(
Set.of(node(0), node(1)),
- JobDescriptor.builder(ExceptionJob.class).build());
+ JobDescriptor.builder(ExceptionJob.class).build(), null);
assertComputeExceptionWithClassAndMessage(getExceptionInJobExecutionAsync(executions.get(node(0))));
@@ -402,7 +412,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
var key = Tuple.create().set(COLUMN_KEY, 1);
IgniteException cause = getExceptionInJobExecutionAsync(
- client().compute().submit(JobTarget.colocated(TABLE_NAME, key), JobDescriptor.builder(ExceptionJob.class).build()));
+ client().compute().submit(JobTarget.colocated(TABLE_NAME, key), JobDescriptor.builder(ExceptionJob.class).build(), null));
assertComputeExceptionWithClassAndMessage(cause);
}
@@ -412,7 +422,11 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
var key = Tuple.create().set(COLUMN_KEY, 1);
IgniteException cause = getExceptionInJobExecutionSync(
- () -> client().compute().execute(JobTarget.colocated(TABLE_NAME, key), JobDescriptor.builder(ExceptionJob.class).build())
+ () -> client().compute().execute(
+ JobTarget.colocated(TABLE_NAME, key),
+ JobDescriptor.builder(ExceptionJob.class).build(),
+ null
+ )
);
assertComputeExceptionWithClassAndMessage(cause);
@@ -425,7 +439,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
IgniteCompute igniteCompute = client().compute();
IgniteException cause = getExceptionInJobExecutionAsync(
- igniteCompute.submit(JobTarget.colocated(TABLE_NAME, key), JobDescriptor.builder(ExceptionJob.class).build())
+ igniteCompute.submit(JobTarget.colocated(TABLE_NAME, key), JobDescriptor.builder(ExceptionJob.class).build(), null)
);
assertComputeExceptionWithStackTrace(cause);
@@ -437,7 +451,11 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
var key = Tuple.create().set(COLUMN_KEY, 2);
IgniteException cause = getExceptionInJobExecutionSync(
- () -> client().compute().execute(JobTarget.colocated(TABLE_NAME, key), JobDescriptor.builder(ExceptionJob.class).build())
+ () -> client().compute().execute(
+ JobTarget.colocated(TABLE_NAME, key),
+ JobDescriptor.builder(ExceptionJob.class).build(),
+ null
+ )
);
assertComputeExceptionWithStackTrace(cause);
@@ -450,8 +468,9 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
IgniteCompute igniteCompute = client().compute();
IgniteException cause = getExceptionInJobExecutionAsync(
- igniteCompute.submit(JobTarget.colocated(TABLE_NAME, key, mapper), JobDescriptor.builder(ExceptionJob.class)
- .build())
+ igniteCompute.submit(JobTarget.colocated(
+ TABLE_NAME, key, mapper), JobDescriptor.builder(ExceptionJob.class).build(), null
+ )
);
assertComputeExceptionWithClassAndMessage(cause);
@@ -464,7 +483,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
IgniteException cause = getExceptionInJobExecutionSync(() -> client().compute().execute(
JobTarget.colocated(TABLE_NAME, key, mapper),
- JobDescriptor.builder(ExceptionJob.class).build())
+ JobDescriptor.builder(ExceptionJob.class).build(), null)
);
assertComputeExceptionWithClassAndMessage(cause);
@@ -478,7 +497,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
IgniteCompute igniteCompute = client().compute();
IgniteException cause = getExceptionInJobExecutionAsync(
- igniteCompute.submit(JobTarget.colocated(TABLE_NAME, key, mapper), JobDescriptor.builder(ExceptionJob.class).build())
+ igniteCompute.submit(JobTarget.colocated(TABLE_NAME, key, mapper), JobDescriptor.builder(ExceptionJob.class).build(), null)
);
assertComputeExceptionWithStackTrace(cause);
@@ -492,7 +511,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
IgniteException cause = getExceptionInJobExecutionSync(
() -> client().compute().execute(
- JobTarget.colocated(TABLE_NAME, key, mapper), JobDescriptor.builder(ExceptionJob.class).build())
+ JobTarget.colocated(TABLE_NAME, key, mapper), JobDescriptor.builder(ExceptionJob.class).build(), null)
);
assertComputeExceptionWithStackTrace(cause);
@@ -542,7 +561,8 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
IgniteCompute igniteCompute = client().compute();
JobExecution<String> tupleExecution = igniteCompute.submit(
- JobTarget.colocated(TABLE_NAME, keyTuple), JobDescriptor.builder(NodeNameJob.class).build());
+ JobTarget.colocated(TABLE_NAME, keyTuple), JobDescriptor.builder(NodeNameJob.class).build(), null
+ );
String expectedNode = "itcct_n_" + port;
assertThat(tupleExecution.resultAsync(), willBe(expectedNode));
@@ -558,7 +578,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
IgniteCompute igniteCompute = client().compute();
Mapper<TestPojo> keyMapper = Mapper.of(TestPojo.class);
JobExecution<String> pojoExecution = igniteCompute.submit(
- JobTarget.colocated(TABLE_NAME, keyPojo, keyMapper), JobDescriptor.builder(NodeNameJob.class).build());
+ JobTarget.colocated(TABLE_NAME, keyPojo, keyMapper), JobDescriptor.builder(NodeNameJob.class).build(), null);
String expectedNode = "itcct_n_" + port;
assertThat(pojoExecution.resultAsync(), willBe(expectedNode));
@@ -573,7 +593,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
int sleepMs = 1_000_000;
IgniteCompute igniteCompute = client().compute();
- JobExecution<String> tupleExecution = igniteCompute.submit(
+ JobExecution<Void> tupleExecution = igniteCompute.submit(
JobTarget.colocated(TABLE_NAME, keyTuple), JobDescriptor.builder(SleepJob.class).build(), sleepMs);
await().until(tupleExecution::stateAsync, willBe(jobStateWithStatus(EXECUTING)));
@@ -591,7 +611,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
IgniteCompute igniteCompute = client().compute();
Mapper<TestPojo> keyMapper = Mapper.of(TestPojo.class);
- JobExecution<String> pojoExecution = igniteCompute.submit(
+ JobExecution<Void> pojoExecution = igniteCompute.submit(
JobTarget.colocated(TABLE_NAME, keyPojo, keyMapper), JobDescriptor.builder(SleepJob.class).build(), sleepMs);
await().until(pojoExecution::stateAsync, willBe(jobStateWithStatus(EXECUTING)));
@@ -609,7 +629,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
IgniteCompute igniteCompute = client().compute();
JobTarget target = JobTarget.node(node(0));
List<DeploymentUnit> units = List.of(new DeploymentUnit("u", "latest"));
- igniteCompute.executeAsync(target, JobDescriptor.builder(NodeNameJob.class).units(units).build()).join();
+ igniteCompute.executeAsync(target, JobDescriptor.builder(NodeNameJob.class).units(units).build(), null).join();
});
var cause = (IgniteException) ex.getCause();
@@ -627,7 +647,9 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
JobTarget.colocated(TABLE_NAME, Tuple.create().set(COLUMN_KEY, 1)),
JobDescriptor.builder(NodeNameJob.class)
.units(new DeploymentUnit("u", "latest"))
- .build()).join());
+ .build(),
+ null
+ ).join());
var cause = (IgniteException) ex.getCause();
assertThat(cause.getMessage(), containsString("Deployment unit u:latest doesn't exist"));
@@ -641,7 +663,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
Builder builder = IgniteClient.builder().addresses(getClientAddresses().toArray(new String[0]));
try (IgniteClient client = builder.build()) {
int delayMs = 3000;
- CompletableFuture<String> jobFut = client.compute().executeAsync(
+ CompletableFuture<Void> jobFut = client.compute().executeAsync(
JobTarget.node(node(0)), JobDescriptor.builder(SleepJob.class).build(), delayMs);
// Wait a bit and close the connection.
@@ -663,7 +685,6 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
testEchoArg(BigDecimal.TEN);
testEchoArg(UUID.randomUUID());
testEchoArg("string");
- testEchoArg(new byte[] {1, 2, 3});
testEchoArg(new BitSet(10));
testEchoArg(LocalDate.now());
testEchoArg(LocalTime.now());
@@ -680,10 +701,10 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
Mapper<TestPojo> mapper = Mapper.of(TestPojo.class);
TestPojo pojoKey = new TestPojo(1);
Tuple tupleKey = Tuple.create().set("key", pojoKey.key);
- JobDescriptor job = JobDescriptor.builder(NodeNameJob.class).build();
+ JobDescriptor<Object, String> job = JobDescriptor.builder(NodeNameJob.class).build();
- var tupleRes = client().compute().execute(JobTarget.colocated(tableName, tupleKey), job);
- var pojoRes = client().compute().execute(JobTarget.colocated(tableName, pojoKey, mapper), job);
+ var tupleRes = client().compute().execute(JobTarget.colocated(tableName, tupleKey), job, null);
+ var pojoRes = client().compute().execute(JobTarget.colocated(tableName, pojoKey, mapper), job, null);
assertEquals(tupleRes, pojoRes);
}
@@ -694,8 +715,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
BigDecimal res = client().compute().execute(
JobTarget.node(node(0)),
JobDescriptor.builder(DecimalJob.class).build(),
- number,
- scale);
+ number + "," + scale);
var expected = new BigDecimal(number).setScale(scale, RoundingMode.HALF_UP);
assertEquals(expected, res);
@@ -703,7 +723,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
@Test
void testExecuteMapReduce() throws Exception {
- TaskExecution<String> execution = client().compute().submitMapReduce(List.of(), MapReduceNodeNameTask.class.getName());
+ TaskExecution<String> execution = client().compute().submitMapReduce(List.of(), MapReduceNodeNameTask.class.getName(), null);
List<Matcher<? super String>> nodeNames = sortedNodes().stream()
.map(ClusterNode::name)
@@ -721,7 +741,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
@Test
void testExecuteMapReduceWithArgs() {
TaskExecution<String> execution = client().compute()
- .submitMapReduce(List.of(), MapReduceArgsTask.class.getName(), 1, "2", 3.3);
+ .submitMapReduce(List.of(), MapReduceArgsTask.class.getName(), "1:2:3.3");
assertThat(execution.resultAsync(), willBe(containsString("1_2_3.3")));
assertThat(execution.stateAsync(), willBe(taskStateWithStatus(TaskStatus.COMPLETED)));
@@ -729,9 +749,10 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
@ParameterizedTest
@ValueSource(classes = {MapReduceExceptionOnSplitTask.class, MapReduceExceptionOnReduceTask.class})
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-22596")
void testExecuteMapReduceExceptionPropagation(Class<?> taskClass) {
IgniteException cause = getExceptionInJobExecutionAsync(new TaskToJobExecutionWrapper<>(
- client().compute().submitMapReduce(List.of(), taskClass.getName()))
+ client().compute().submitMapReduce(List.of(), taskClass.getName(), null))
);
assertThat(cause.getMessage(), containsString("Custom job error"));
@@ -742,13 +763,16 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
}
private void testEchoArg(Object arg) {
- Object res = client().compute().execute(JobTarget.node(node(0)), JobDescriptor.builder(EchoJob.class).build(), arg, arg.toString());
+ Object res = client().compute().execute(JobTarget.node(node(0)), JobDescriptor.builder(EchoJob.class).build(), arg);
if (arg instanceof byte[]) {
assertArrayEquals((byte[]) arg, (byte[]) res);
} else {
assertEquals(arg, res);
}
+
+ String str = client().compute().execute(JobTarget.node(node(0)), JobDescriptor.builder(ToStringJob.class).build(), arg);
+ assertEquals(arg.toString(), str);
}
private ClusterNode node(int idx) {
@@ -761,37 +785,38 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
.collect(Collectors.toList());
}
- private static class NodeNameJob implements ComputeJob<String> {
+ private static class NodeNameJob implements ComputeJob<Object, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
- return completedFuture(
- context.ignite().name() + Arrays.stream(args).map(Object::toString).collect(Collectors.joining("_")));
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Object arg) {
+ return completedFuture(context.ignite().name() + (arg == null ? "" : arg.toString()));
}
}
- private static class ConcatJob implements ComputeJob<String> {
+ private static class ConcatJob implements ComputeJob<String, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, String args) {
if (args == null) {
return nullCompletedFuture();
}
return completedFuture(
- Arrays.stream(args).map(o -> o == null ? "null" : o.toString()).collect(Collectors.joining("_")));
+ Arrays.stream(args.split(":"))
+ .map(o -> o == null ? "null" : o.toString())
+ .collect(Collectors.joining("_")));
}
}
- private static class IgniteExceptionJob implements ComputeJob<String> {
+ private static class IgniteExceptionJob implements ComputeJob<Object, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Object args) {
throw new CustomException(TRACE_ID, COLUMN_ALREADY_EXISTS_ERR, "Custom job error", null);
}
}
- private static class ExceptionJob implements ComputeJob<String> {
+ private static class ExceptionJob implements ComputeJob<Boolean, String> {
@Override
- public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
- boolean asyncJob = args.length > 0 && (Boolean) args[0];
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Boolean arg) {
+ boolean asyncJob = arg != null && arg;
if (asyncJob) {
return failedFuture(new ArithmeticException("math err"));
@@ -801,26 +826,29 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
}
}
- private static class EchoJob implements ComputeJob<Object> {
+ private static class EchoJob implements ComputeJob<Object, Object> {
@Override
- public CompletableFuture<Object> executeAsync(JobExecutionContext context, Object... args) {
- var value = args[0];
+ public CompletableFuture<Object> executeAsync(JobExecutionContext context, Object arg) {
+ return completedFuture(arg);
+ }
+ }
- if (!(value instanceof byte[])) {
- var expectedString = (String) args[1];
- var valueString = value == null ? "null" : value.toString();
- assertEquals(expectedString, valueString, "Unexpected string representation of value");
+ private static class ToStringJob implements ComputeJob<Object, String> {
+ @Override
+ public CompletableFuture<String> executeAsync(JobExecutionContext context, Object arg) {
+ if (arg instanceof byte[]) {
+ return completedFuture(Arrays.toString((byte[]) arg));
}
- return completedFuture(args[0]);
+ return completedFuture(arg.toString());
}
}
- private static class SleepJob implements ComputeJob<Void> {
+ private static class SleepJob implements ComputeJob<Integer, Void> {
@Override
- public @Nullable CompletableFuture<Void> executeAsync(JobExecutionContext context, Object... args) {
+ public @Nullable CompletableFuture<Void> executeAsync(JobExecutionContext context, Integer args) {
try {
- Thread.sleep((Integer) args[0]);
+ Thread.sleep(args);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
@@ -829,12 +857,12 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
}
}
- private static class AsyncSleepJob implements ComputeJob<Void> {
+ private static class AsyncSleepJob implements ComputeJob<Integer, Void> {
@Override
- public @Nullable CompletableFuture<Void> executeAsync(JobExecutionContext context, Object... args) {
+ public @Nullable CompletableFuture<Void> executeAsync(JobExecutionContext context, Integer args) {
return CompletableFuture.runAsync(() -> {
try {
- Thread.sleep((Integer) args[0]);
+ Thread.sleep(args);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
@@ -842,18 +870,21 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
}
}
- private static class DecimalJob implements ComputeJob<BigDecimal> {
+ private static class DecimalJob implements ComputeJob<String, BigDecimal> {
@Override
- public CompletableFuture<BigDecimal> executeAsync(JobExecutionContext context, Object... args) {
- return completedFuture(new BigDecimal((String) args[0]).setScale((Integer) args[1], RoundingMode.HALF_UP));
+ public CompletableFuture<BigDecimal> executeAsync(JobExecutionContext context, String arg) {
+ @SuppressWarnings("DataFlowIssue")
+ var args = arg.split(",", 2);
+
+ return completedFuture(new BigDecimal(args[0]).setScale(Integer.parseInt(args[1]), RoundingMode.HALF_UP));
}
}
- private static class MapReduceNodeNameTask implements MapReduceTask<String> {
+ private static class MapReduceNodeNameTask implements MapReduceTask<String, Object, String, String> {
@Override
- public CompletableFuture<List<MapReduceJob>> splitAsync(TaskExecutionContext context, Object... args) {
+ public CompletableFuture<List<MapReduceJob<Object, String>>> splitAsync(TaskExecutionContext context, String args) {
return completedFuture(context.ignite().clusterNodes().stream()
- .map(node -> MapReduceJob.builder()
+ .map(node -> MapReduceJob.<Object, String>builder()
.jobDescriptor(JobDescriptor.builder(NodeNameJob.class).build())
.nodes(Set.of(node))
.args(args)
@@ -862,18 +893,18 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
}
@Override
- public CompletableFuture<String> reduceAsync(TaskExecutionContext context, Map<UUID, ?> results) {
+ public CompletableFuture<String> reduceAsync(TaskExecutionContext context, Map<UUID, String> results) {
return completedFuture(results.values().stream()
.map(String.class::cast)
.collect(Collectors.joining(",")));
}
}
- private static class MapReduceArgsTask implements MapReduceTask<String> {
+ private static class MapReduceArgsTask implements MapReduceTask<String, String, String, String> {
@Override
- public CompletableFuture<List<MapReduceJob>> splitAsync(TaskExecutionContext context, Object... args) {
+ public CompletableFuture<List<MapReduceJob<String, String>>> splitAsync(TaskExecutionContext context, String args) {
return completedFuture(context.ignite().clusterNodes().stream()
- .map(node -> MapReduceJob.builder()
+ .map(node -> MapReduceJob.<String, String>builder()
.jobDescriptor(JobDescriptor.builder(ConcatJob.class).build())
.nodes(Set.of(node))
.args(args)
@@ -882,31 +913,31 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
}
@Override
- public CompletableFuture<String> reduceAsync(TaskExecutionContext context, Map<UUID, ?> results) {
+ public CompletableFuture<String> reduceAsync(TaskExecutionContext context, Map<UUID, String> results) {
return completedFuture(results.values().stream()
.map(String.class::cast)
.collect(Collectors.joining(",")));
}
}
- private static class MapReduceExceptionOnSplitTask implements MapReduceTask<String> {
+ private static class MapReduceExceptionOnSplitTask implements MapReduceTask<Object, Object, Object, String> {
@Override
- public CompletableFuture<List<MapReduceJob>> splitAsync(TaskExecutionContext context, Object... args) {
+ public CompletableFuture<List<MapReduceJob<Object, Object>>> splitAsync(TaskExecutionContext context, Object args) {
throw new CustomException(TRACE_ID, COLUMN_ALREADY_EXISTS_ERR, "Custom job error", null);
}
@Override
- public CompletableFuture<String> reduceAsync(TaskExecutionContext context, Map<UUID, ?> results) {
+ public CompletableFuture<String> reduceAsync(TaskExecutionContext context, Map<UUID, Object> results) {
return completedFuture("expected split exception");
}
}
- private static class MapReduceExceptionOnReduceTask implements MapReduceTask<String> {
+ private static class MapReduceExceptionOnReduceTask implements MapReduceTask<Object, Object, String, String> {
@Override
- public CompletableFuture<List<MapReduceJob>> splitAsync(TaskExecutionContext context, Object... args) {
+ public CompletableFuture<List<MapReduceJob<Object, String>>> splitAsync(TaskExecutionContext context, Object args) {
return completedFuture(context.ignite().clusterNodes().stream()
- .map(node -> MapReduceJob.builder()
+ .map(node -> MapReduceJob.<Object, String>builder()
.jobDescriptor(JobDescriptor.builder(NodeNameJob.class).build())
.nodes(Set.of(node))
.args(args)
@@ -915,7 +946,7 @@ public class ItThinClientComputeTest extends ItAbstractThinClientTest {
}
@Override
- public CompletableFuture<String> reduceAsync(TaskExecutionContext context, Map<UUID, ?> results) {
+ public CompletableFuture<String> reduceAsync(TaskExecutionContext context, Map<UUID, String> results) {
throw new CustomException(TRACE_ID, COLUMN_ALREADY_EXISTS_ERR, "Custom job error", null);
}
}
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientPartitionAwarenessTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientPartitionAwarenessTest.java
index dc9b05ccea..e2e3d7b541 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientPartitionAwarenessTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientPartitionAwarenessTest.java
@@ -89,7 +89,7 @@ public class ItThinClientPartitionAwarenessTest extends ItAbstractThinClientTest
// Get actual primary node using compute.
Tuple keyTuple = Tuple.create().set("key", key);
var primaryNodeName = proxyClient.compute().execute(
- JobTarget.colocated(TABLE_NAME, keyTuple), JobDescriptor.builder(NodeNameJob.class.getName()).build());
+ JobTarget.colocated(TABLE_NAME, keyTuple), JobDescriptor.builder(NodeNameJob.class.getName()).build(), null);
// Perform request and check routing with proxy.
resetRequestCount();
@@ -122,9 +122,14 @@ public class ItThinClientPartitionAwarenessTest extends ItAbstractThinClientTest
return null;
}
- private static class NodeNameJob implements ComputeJob<String> {
+ private static class NodeNameJob implements ComputeJob<Object[], String> {
@Override
public CompletableFuture<String> executeAsync(JobExecutionContext context, Object... args) {
+ if (args == null) {
+ //noinspection resource
+ return completedFuture(context.ignite().name());
+ }
+
//noinspection resource
return completedFuture(
context.ignite().name() + Arrays.stream(args).map(Object::toString).collect(Collectors.joining("_")));
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/streamer/ItAbstractDataStreamerTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/streamer/ItAbstractDataStreamerTest.java
index 65b20f2d63..d95a02cdd5 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/streamer/ItAbstractDataStreamerTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/streamer/ItAbstractDataStreamerTest.java
@@ -381,8 +381,8 @@ public abstract class ItAbstractDataStreamerTest extends ClusterPerClassIntegrat
ReceiverDescriptor.builder(TestReceiver.class).build(),
resultSubscriber,
DataStreamerOptions.builder().retryLimit(0).build(),
- "arg1",
- 123);
+ "arg1"
+ );
// Same ID goes to the same partition.
publisher.submit(tuple(1, "val1"));
@@ -394,7 +394,7 @@ public abstract class ItAbstractDataStreamerTest extends ClusterPerClassIntegrat
if (returnResults) {
assertEquals(1, resultSubscriber.items.size());
- assertEquals("Received: 3 items, 2 args", resultSubscriber.items.iterator().next());
+ assertEquals("Received: 3 items, arg1 arg", resultSubscriber.items.iterator().next());
}
}
@@ -414,8 +414,8 @@ public abstract class ItAbstractDataStreamerTest extends ClusterPerClassIntegrat
t -> t,
t -> t.intValue(0),
ReceiverDescriptor.builder(NodeNameReceiver.class).build(),
- null,
- null);
+ null, null, null
+ );
for (int i = 0; i < count; i++) {
publisher.submit(tupleKey(i));
@@ -522,14 +522,14 @@ public abstract class ItAbstractDataStreamerTest extends ClusterPerClassIntegrat
}
@SuppressWarnings("resource")
- private static class TestReceiver implements DataStreamerReceiver<String, String> {
+ private static class TestReceiver implements DataStreamerReceiver<String, Object, String> {
@Override
- public CompletableFuture<List<String>> receive(List<String> page, DataStreamerReceiverContext ctx, Object... args) {
- if ("throw".equals(args[0])) {
+ public CompletableFuture<List<String>> receive(List<String> page, DataStreamerReceiverContext ctx, Object arg) {
+ if ("throw".equals(arg)) {
throw new ArithmeticException("test");
}
- if ("throw-async".equals(args[0])) {
+ if ("throw-async".equals(arg)) {
return CompletableFuture.failedFuture(new ArithmeticException("test"));
}
@@ -540,18 +540,16 @@ public abstract class ItAbstractDataStreamerTest extends ClusterPerClassIntegrat
assertNotNull(ctx.ignite().tables().table(TABLE_NAME));
- assertEquals(2, args.length);
- assertEquals("arg1", args[0]);
- assertEquals(123, args[1]);
+ assertEquals("arg1", arg);
- return CompletableFuture.completedFuture(List.of("Received: " + page.size() + " items, " + args.length + " args"));
+ return CompletableFuture.completedFuture(List.of("Received: " + page.size() + " items, " + arg + " arg"));
}
}
@SuppressWarnings("resource")
- private static class NodeNameReceiver implements DataStreamerReceiver<Integer, Void> {
+ private static class NodeNameReceiver implements DataStreamerReceiver<Integer, Object, Void> {
@Override
- public @Nullable CompletableFuture<List<Void>> receive(List<Integer> page, DataStreamerReceiverContext ctx, Object... args) {
+ public @Nullable CompletableFuture<List<Void>> receive(List<Integer> page, DataStreamerReceiverContext ctx, Object arg) {
var nodeName = ctx.ignite().name();
RecordView<Tuple> view = ctx.ignite().tables().table(TABLE_NAME).recordView();
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueBinaryViewImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueBinaryViewImpl.java
index 243b551ddd..d450b60d76 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueBinaryViewImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueBinaryViewImpl.java
@@ -570,14 +570,14 @@ public class KeyValueBinaryViewImpl extends AbstractTableView<Entry<Tuple, Tuple
}
@Override
- public <E, V, R> CompletableFuture<Void> streamData(
+ public <E, V, R, A> CompletableFuture<Void> streamData(
Publisher<E> publisher,
Function<E, Entry<Tuple, Tuple>> keyFunc,
Function<E, V> payloadFunc,
- ReceiverDescriptor receiver,
+ ReceiverDescriptor<A> receiver,
@Nullable Flow.Subscriber<R> resultSubscriber,
@Nullable DataStreamerOptions options,
- Object... receiverArgs) {
+ A receiverArg) {
// TODO: IGNITE-22285 Embedded Data Streamer with Receiver.
throw new UnsupportedOperationException("Not implemented yet");
}
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueViewImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueViewImpl.java
index 80b79d4101..ad3f771d42 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueViewImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueViewImpl.java
@@ -787,14 +787,14 @@ public class KeyValueViewImpl<K, V> extends AbstractTableView<Entry<K, V>> imple
}
@Override
- public <E, V1, R> CompletableFuture<Void> streamData(
+ public <E, V1, R, A> CompletableFuture<Void> streamData(
Publisher<E> publisher,
Function<E, Entry<K, V>> keyFunc,
Function<E, V1> payloadFunc,
- ReceiverDescriptor receiver,
+ ReceiverDescriptor<A> receiver,
@Nullable Flow.Subscriber<R> resultSubscriber,
@Nullable DataStreamerOptions options,
- Object... receiverArgs) {
+ A receiverArg) {
// TODO: IGNITE-22285 Embedded Data Streamer with Receiver.
throw new UnsupportedOperationException("Not implemented yet");
}
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingViewBase.java b/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingViewBase.java
index f396284be3..f4cf5e01a4 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingViewBase.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingViewBase.java
@@ -58,14 +58,14 @@ abstract class PublicApiThreadingViewBase<T> implements DataStreamerTarget<T>, C
}
@Override
- public <E, V, R> CompletableFuture<Void> streamData(
+ public <E, V, R, A> CompletableFuture<Void> streamData(
Publisher<E> publisher,
Function<E, T> keyFunc,
Function<E, V> payloadFunc,
- ReceiverDescriptor receiver,
+ ReceiverDescriptor<A> receiver,
@Nullable Flow.Subscriber<R> resultSubscriber,
@Nullable DataStreamerOptions options,
- Object... receiverArgs) {
+ A receiverArg) {
return executeAsyncOp(() -> streamerTarget.streamData(
publisher,
keyFunc,
@@ -73,7 +73,7 @@ abstract class PublicApiThreadingViewBase<T> implements DataStreamerTarget<T>, C
receiver,
resultSubscriber,
options,
- receiverArgs));
+ receiverArg));
}
@Override
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/RecordBinaryViewImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/RecordBinaryViewImpl.java
index b54db7f79a..b901499305 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/RecordBinaryViewImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/RecordBinaryViewImpl.java
@@ -518,14 +518,14 @@ public class RecordBinaryViewImpl extends AbstractTableView<Tuple> implements Re
}
@Override
- public <E, V, R> CompletableFuture<Void> streamData(
+ public <E, V, R, A> CompletableFuture<Void> streamData(
Publisher<E> publisher,
Function<E, Tuple> keyFunc,
Function<E, V> payloadFunc,
- ReceiverDescriptor receiver,
+ ReceiverDescriptor<A> receiver,
@Nullable Flow.Subscriber<R> resultSubscriber,
@Nullable DataStreamerOptions options,
- Object... receiverArgs) {
+ A receiverArg) {
// TODO: IGNITE-22285 Embedded Data Streamer with Receiver.
throw new UnsupportedOperationException("Not implemented yet");
}
diff --git a/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java b/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java
index e759b3fb6e..57bc3903e0 100644
--- a/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java
+++ b/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java
@@ -570,14 +570,14 @@ public class RecordViewImpl<R> extends AbstractTableView<R> implements RecordVie
}
@Override
- public <E, V, R1> CompletableFuture<Void> streamData(
+ public <E, V, R1, A> CompletableFuture<Void> streamData(
Publisher<E> publisher,
Function<E, R> keyFunc,
Function<E, V> payloadFunc,
- ReceiverDescriptor receiver,
+ ReceiverDescriptor<A> receiver,
@Nullable Flow.Subscriber<R1> resultSubscriber,
@Nullable DataStreamerOptions options,
- Object... receiverArgs) {
+ A receiverArg) {
// TODO: IGNITE-22285 Embedded Data Streamer with Receiver
throw new UnsupportedOperationException("Not implemented yet");
}