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