package org.infinispan.interceptors.impl;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import org.infinispan.commands.VisitableCommand;
import org.infinispan.context.InvocationContext;
import org.infinispan.interceptors.InvocationCallback;
import org.infinispan.interceptors.InvocationStage;
import org.infinispan.util.concurrent.CompletableFutures;
/**
* Invocation stage representing a computation that may or may not be done yet.
*
* It is only meant to support the simplest asynchronous invocation,
* {@link org.infinispan.interceptors.BaseAsyncInterceptor#asyncValue(CompletableFuture)}.
*
* @author Dan Berindei
* @since 9.0
*/
public class SimpleAsyncInvocationStage extends InvocationStage {
protected final CompletableFuture<Object> future;
@SuppressWarnings("unchecked")
public SimpleAsyncInvocationStage(CompletionStage<?> future) {
this.future = (CompletableFuture<Object>) future;
}
public SimpleAsyncInvocationStage(Throwable throwable) {
this.future = CompletableFutures.completedExceptionFuture(throwable);
}
@Override
public Object get() throws Throwable {
try {
return CompletableFutures.await(future);
} catch (ExecutionException e) {
throw e.getCause();
}
}
@Override
public boolean isDone() {
return future.isDone();
}
@Override
public CompletableFuture<Object> toCompletableFuture() {
return future;
}
@Override
public Object addCallback(InvocationContext ctx, VisitableCommand command,
InvocationCallback function) {
if (future.isDone()) {
Object rv;
Throwable throwable;
try {
rv = future.getNow(null);
throwable = null;
} catch (Throwable t) {
rv = null;
throwable = CompletableFutures.extractException(t);
}
try {
return function.apply(ctx, command, rv, throwable);
} catch (Throwable t) {
return new SimpleAsyncInvocationStage(t);
}
}
return new QueueAsyncInvocationStage(ctx, command, future, function);
}
}