use of org.infinispan.remoting.rpc.ResponseFilter in project infinispan by infinispan.
the class Transport method invokeCommandStaggered.
/**
* Invoke a command on a collection of nodes and pass the responses to a {@link ResponseCollector}.
* <p>
* The command is only sent immediately to the first target, and there is an implementation-dependent
* delay before sending the command to each target. There is no delay if the target responds or leaves
* the cluster. The remaining targets are skipped if {@link ResponseCollector#addResponse(Address, Response)}
* returns a non-{@code null} value.
* <p>
* The command is only executed on the remote nodes.
*
* @since 9.1
*/
@Experimental
default <T> CompletionStage<T> invokeCommandStaggered(Collection<Address> targets, ReplicableCommand command, ResponseCollector<T> collector, DeliverOrder deliverOrder, long timeout, TimeUnit unit) {
// Implement the new methods on top of invokeRemotelyAsync to support custom implementations
AtomicReference<Object> result = new AtomicReference<>(null);
try {
ResponseFilter responseFilter = new ResponseFilter() {
@Override
public boolean isAcceptable(Response response, Address sender) {
// Guarantee collector.addResponse() isn't called concurrently
synchronized (result) {
if (result.get() != null)
return false;
T t = collector.addResponse(sender, response);
result.set(t);
return t != null;
}
}
@Override
public boolean needMoreResponses() {
return result.get() == null;
}
};
return invokeRemotelyAsync(targets, command, ResponseMode.WAIT_FOR_VALID_RESPONSE, unit.toMillis(timeout), responseFilter, deliverOrder, false).thenApply(map -> {
synchronized (result) {
if (result.get() != null) {
return (T) result.get();
} else {
// Prevent further calls to collector.addResponse()
result.set(new Object());
return collector.finish();
}
}
});
} catch (Exception e) {
throw Util.rewrapAsCacheException(e);
}
}
use of org.infinispan.remoting.rpc.ResponseFilter in project infinispan by infinispan.
the class Transport method invokeRemotely.
/**
* @deprecated Since 9.2, please use {@link #invokeRemotelyAsync(Collection, ReplicableCommand, ResponseMode, long, ResponseFilter, DeliverOrder, boolean)} instead.
*/
@Deprecated
default Map<Address, Response> invokeRemotely(Map<Address, ReplicableCommand> rpcCommands, ResponseMode mode, long timeout, ResponseFilter responseFilter, DeliverOrder deliverOrder, boolean anycast) throws Exception {
// This overload didn't have an async version, so implement it on top of the regular invokeRemotelyAsync
Map<Address, Response> result = new ConcurrentHashMap<>(rpcCommands.size());
ResponseFilter partResponseFilter = new ResponseFilter() {
@Override
public boolean isAcceptable(Response response, Address sender) {
// Guarantee collector.addResponse() isn't called concurrently
synchronized (result) {
result.put(sender, response);
return responseFilter.isAcceptable(response, sender);
}
}
@Override
public boolean needMoreResponses() {
return responseFilter.needMoreResponses();
}
};
List<CompletableFuture<Map<Address, Response>>> futures = new ArrayList<>(rpcCommands.size());
for (Map.Entry<Address, ReplicableCommand> e : rpcCommands.entrySet()) {
futures.add(invokeRemotelyAsync(Collections.singleton(e.getKey()), e.getValue(), mode, timeout, partResponseFilter, deliverOrder, anycast));
}
try {
// no need to set a timeout for the future. The rpc invocation is guaranteed to complete within the timeout
// milliseconds
CompletableFutures.await(CompletableFuture.allOf(futures.toArray(new CompletableFuture[rpcCommands.size()])));
return result;
} catch (ExecutionException e) {
Throwable cause = e.getCause();
cause.addSuppressed(new TraceException());
throw Util.rewrapAsCacheException(cause);
}
}
Aggregations