com.yahoo.maha.parrequest2.future.ComposableFutureFuture Maven / Gradle / Ivy
// Copyright 2017, Yahoo Holdings Inc.
// Licensed under the terms of the Apache License 2.0. Please see LICENSE file in project root for terms.
package com.yahoo.maha.parrequest2.future;
import java.util.function.Function;
import com.google.common.util.concurrent.AbstractFuture;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.Uninterruptibles;
import com.yahoo.maha.parrequest2.EitherUtils;
import scala.util.Either;
import com.yahoo.maha.parrequest2.GeneralError;
import java.util.concurrent.CancellationException;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
/**
* This class takes a future and a function, which produces a future, to apply to the future on completion and returns a
* future which represents the result of future returned by the function.
*/
class ComposableFutureFuture extends AbstractFuture> implements Runnable {
class ResultListener implements Runnable {
private final CombinableRequest resultFuture;
public ResultListener(CombinableRequest resultFuture) {
this.resultFuture = resultFuture;
}
@Override
public void run() {
try {
checkState(this.resultFuture.asFuture().isDone(),
"Tried to set value from result future which is not done");
Either returnValue = Uninterruptibles.getUninterruptibly(this.resultFuture.asFuture());
set(returnValue);
} catch (CancellationException e) {
cancel(false);
} catch (Throwable t) {
setException(t);
}
}
}
private final ListenableFuture> future;
private final Function> fn;
private final ParallelServiceExecutor executor;
public ComposableFutureFuture(ParallelServiceExecutor executor,
final ListenableFuture> future,
Function> fn) {
checkNotNull(executor, "executor cannot be null");
checkNotNull(future, "future cannot be null");
checkNotNull(fn, "function cannot be null");
this.executor = executor;
this.future = future;
this.fn = fn;
executor.addListener(this, new Runnable() {
@Override
public void run() {
if (isCancelled()) {
if (future != null) {
future.cancel(wasInterrupted());
}
}
}
});
executor.addListener(future, this);
}
public void addResultListener(final CombinableRequest resultFuture) {
executor.addListener(this, new Runnable() {
@Override
public void run() {
if (isCancelled()) {
if (resultFuture.asFuture() != null) {
resultFuture.asFuture().cancel(wasInterrupted());
}
}
}
});
executor.addListener(resultFuture.asFuture(), new ResultListener(resultFuture));
}
@Override
public void run() {
try {
checkState(future.isDone(),
"Tried to set value from future which is not done");
Either returnValue = Uninterruptibles.getUninterruptibly(future);
if (returnValue.isLeft()) {
set(EitherUtils.castLeft(returnValue));
} else {
T rightValue = returnValue.right().get();
addResultListener(fn.apply(rightValue));
}
} catch (CancellationException e) {
cancel(false);
} catch (Throwable t) {
setException(t);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy