io.hekate.messaging.operation.Aggregate Maven / Gradle / Ivy
Show all versions of hekate-core Show documentation
/*
* Copyright 2020 The Hekate Project
*
* The Hekate Project 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 io.hekate.messaging.operation;
import io.hekate.core.Hekate;
import io.hekate.messaging.MessageTimeoutException;
import io.hekate.messaging.MessagingChannel;
import io.hekate.messaging.MessagingChannelConfig;
import io.hekate.messaging.MessagingFutureException;
import io.hekate.messaging.retry.GenericRetryConfigurer;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
/**
* Aggregate operation.
*
*
* This interface represents a request/response-style broadcast operation of a {@link MessagingChannel}.
* This operation submits the same request message to multiple remote nodes and aggregates their responses.
*
*
* Usage Example
*
* Typical use of this interface is:
*
*
* - Obtain an instance of this interface via the {@link MessagingChannel#newAggregate(Object)} method call
* - Set options (if needed):
*
* - {@link #withTimeout(long, TimeUnit) Request Timeout}
* - {@link #withAffinity(Object) Affinity Key}
* - {@link #withRetry(AggregateRetryConfigurer) Retry Policy}
*
*
* - Execute this operation via the {@link #submit()} method
* - Process results (synchronously or asynchronously)
*
*
*
* ${source: messaging/MessagingServiceJavadocTest.java#aggregate_operation}
*
*
* Shortcut Methods
*
* {@link MessagingChannel} interface provides a set of synchronous and asynchronous shortcut methods for common use cases:
*
*
* - {@link MessagingChannel#aggregate(Object)}
* - {@link MessagingChannel#aggregate(Object, Object)}
* - {@link MessagingChannel#aggregateAsync(Object)}
* - {@link MessagingChannel#aggregateAsync(Object, Object)}
*
*
* @param Message type.
*/
public interface Aggregate {
/**
* Affinity key.
*
*
* Specifying an affinity key ensures that all operation with the same key will always be transmitted over the same network
* connection and will always be processed by the same thread (if the cluster topology doesn't change).
*
*
* @param affinity Affinity key.
*
* @return This instance.
*/
Aggregate withAffinity(Object affinity);
/**
* Overrides the channel's default timeout value for this operation.
*
*
* If this operation can not complete at the specified timeout then this operation will end up in a {@link MessageTimeoutException}.
*
*
*
* Specifying a negative or zero value disables the timeout check.
*
*
* @param timeout Timeout.
* @param unit Unit.
*
* @return This instance.
*
* @see MessagingChannelConfig#setMessagingTimeout(long)
*/
Aggregate withTimeout(long timeout, TimeUnit unit);
/**
* Retry policy for each individual message of the aggregation operation.
*
*
* This policy gets applied to each individual (per-node) message. For example, if aggregation should be performed over 3 nodes
* and an error happens while sending an aggregation message to the second node then this retry policy will be applied only to that
* particular failed message.
*
*
*
* If retry logic should be implemented at the aggregation level (i.e. decide on whether to retry or not by looking at the whole
* {@link AggregateResult}) please see the {@link #withRepeat(AggregateRepeatCondition)} method.
*
*
* @param retry Retry policy.
*
* @return This instance.
*
* @see MessagingChannelConfig#setRetryPolicy(GenericRetryConfigurer)
* @see #withRepeat(AggregateRepeatCondition)
*/
Aggregate withRetry(AggregateRetryConfigurer retry);
/**
* Condition to repeat for the whole {@link Aggregate} operation.
*
*
* If the specified condition evaluates to {@code true} then the whole {@link Aggregate} operation will be repeated from scratch,
* except for the following cases:
*
*
*
* - {@link Aggregate} operation timed out (see {@link #withTimeout(long, TimeUnit)})
* - {@link MessagingChannel}'s cluster topology is empty (i.e. no nodes to perform aggregation)
* - {@link Hekate} node is stopped
*
*
*
* If one of the above is true then {@link Aggregate} will complete with whatever {@link AggregateResult} it has.
*
*
* @param condition Condition.
*
* @return This instance.
*
* @see #withRetry(AggregateRetryConfigurer)
*/
Aggregate withRepeat(AggregateRepeatCondition condition);
/**
* Asynchronously executes this operation.
*
* @return Future result of this operation.
*/
AggregateFuture submit();
/**
* Asynchronously executes this operation and notifies the specified callback upon completion.
*
* @param callback Callback.
*/
default void submit(AggregateCallback callback) {
submit().whenComplete((rslt, err) ->
callback.onComplete(err, rslt)
);
}
/**
* Synchronously executes this operation and returns the result.
*
* @return Result (see {@link AggregateResult#results()}).
*
* @throws MessagingFutureException If operations fails.
* @throws InterruptedException If thread got interrupted while awaiting for this operation to complete.
*/
default Collection results() throws MessagingFutureException, InterruptedException {
return submit().get().results();
}
/**
* Synchronously executes this operation and returns the result.
*
* @return Result.
*
* @throws MessagingFutureException If operations fails.
* @throws InterruptedException If thread got interrupted while awaiting for this operation to complete.
*/
default AggregateResult get() throws MessagingFutureException, InterruptedException {
return submit().get();
}
}