com.yahoo.maha.parrequest2.future.ParRequest3Option 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 com.google.common.util.concurrent.ListenableFuture;
import com.yahoo.maha.parrequest2.EitherUtils;
import com.yahoo.maha.parrequest2.ParCallable;
import scala.util.Either;
import com.yahoo.maha.parrequest2.GeneralError;
import scala.Option;
import scala.Tuple3;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
/**
* This class represents three parallel requests which can be composed synchronously with resultMap, or composed
* asynchronously with map and fold
*/
public class ParRequest3Option extends CombinableRequest, Option, Option>> {
private final ParallelServiceExecutor executor;
private final CombinedFuture3Option combinedFuture3;
ParRequest3Option(String label, ParallelServiceExecutor executor,
ParCallable> firstRequest,
ParCallable> secondRequest,
ParCallable> thirdRequest,
boolean allMustSucceed) {
checkNotNull(executor, "Executor is null");
checkNotNull(firstRequest, "First request is null");
checkNotNull(secondRequest, "Second request is null");
checkNotNull(thirdRequest, "Third request is null");
this.label = label;
this.executor = executor;
//fire requests
final ListenableFuture> firstFuture = executor.submitParCallable(firstRequest);
final ListenableFuture> secondFuture = executor.submitParCallable(secondRequest);
final ListenableFuture> thirdFuture = executor.submitParCallable(thirdRequest);
try {
combinedFuture3 =
CombinedFuture3Option.from(executor, firstFuture, secondFuture, thirdFuture, allMustSucceed);
} catch (Exception e) {
//failed to create combiner, cancel futures and re-throw exception
firstFuture.cancel(false);
secondFuture.cancel(false);
thirdFuture.cancel(false);
throw e;
}
}
ParRequest3Option(String label, ParallelServiceExecutor executor,
CombinableRequest firstRequest,
CombinableRequest secondRequest,
CombinableRequest thirdRequest,
boolean allMustSucceed) {
checkNotNull(executor, "Executor is null");
checkNotNull(firstRequest, "First request is null");
checkNotNull(secondRequest, "Second request is null");
checkNotNull(thirdRequest, "Third request is null");
this.label = label;
this.executor = executor;
combinedFuture3 = CombinedFuture3Option.from(
executor, firstRequest.asFuture(), secondRequest.asFuture(), thirdRequest.asFuture(), allMustSucceed);
}
public Either resultMap(ParFunction, Option, Option>, O> fn) {
Either, Option, Option>>
result =
executor.getEitherSafely(label, combinedFuture3);
return EitherUtils.map(fn, result);
}
public NoopRequest fold(ParFunction errFn,
ParFunction, Option, Option>, O> fn) {
return new NoopRequest(executor, new FoldableFuture<>(executor, combinedFuture3, fn, errFn));
}
public ParRequest map(String label,
ParFunction, Option, Option>, Either> fn) {
return new ParRequest<>(label, executor, new ComposableFuture<>(executor, combinedFuture3, fn));
}
public ParRequest flatMap(String label,
ParFunction, Option, Option>, CombinableRequest> fn) {
return new ParRequest<>(label, executor, new ComposableFutureFuture<>(executor, combinedFuture3, fn));
}
public Either, Option, Option>> get() {
return executor.getEitherSafely(label, combinedFuture3);
}
ListenableFuture, Option, Option>>> asFuture() {
return combinedFuture3;
}
public static class Builder {
private final ParallelServiceExecutor executor;
private Option>> firstParCallable = Option.empty();
private Option>> secondParCallable = Option.empty();
private Option>> thirdParCallable = Option.empty();
private boolean built = false;
private boolean allMustSucceed = false;
private String label = "changethis";
public Builder setLabel(String label) {
this.label = label;
return this;
}
public Builder(ParallelServiceExecutor executor) {
this.executor = executor;
}
public Builder setFirstParCallable(ParCallable> parCallable) {
checkState(firstParCallable.isEmpty(), "Cannot set the first parCallable twice!");
firstParCallable = Option.apply(parCallable);
return this;
}
public Builder setSecondParCallable(ParCallable> parCallable) {
checkState(secondParCallable.isEmpty(), "Cannot set the second parCallable twice!");
secondParCallable = Option.apply(parCallable);
return this;
}
public Builder setThirdParCallable(ParCallable> parCallable) {
checkState(thirdParCallable.isEmpty(), "Cannot set the third parCallable twice!");
thirdParCallable = Option.apply(parCallable);
return this;
}
public Builder allMustSucceed(boolean allMustSucceed) {
this.allMustSucceed = allMustSucceed;
return this;
}
public ParRequest3Option build() {
checkState(!built, "Cannot build a request twice!");
checkState(firstParCallable.isDefined(), "First parCallable not defined!");
checkState(secondParCallable.isDefined(), "Second parCallable not defined!");
checkState(thirdParCallable.isDefined(), "Third parCallable not defined!");
try {
ParCallable> first = ParCallable.from(firstParCallable.get());
ParCallable> second = ParCallable.from(secondParCallable.get());
ParCallable> third = ParCallable.from(thirdParCallable.get());
return new ParRequest3Option<>(label, executor, first, second, third, allMustSucceed);
} finally {
built = true;
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy