com.yahoo.maha.parrequest2.future.ParRequest 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.Futures;
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.Function1;
import scala.Unit;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
/**
* This class represents a parallel request which can be composed synchronously with resultMap, or composed
* asynchronously with map and fold
*/
public class ParRequest extends CombinableRequest {
private final ParallelServiceExecutor executor;
private final ListenableFuture> future;
ParRequest(String label, ParallelServiceExecutor executor, ParCallable> request) {
checkNotNull(executor, "Executor is null");
checkNotNull(request, "Request is null");
this.label = label;
this.executor = executor;
//fire request
this.future = executor.submitParCallable(request);
}
ParRequest(String label, ParallelServiceExecutor executor, ListenableFuture> future) {
checkNotNull(executor, "Executor is null");
checkNotNull(future, "Future is null");
this.label = label;
this.executor = executor;
this.future = future;
}
public Either resultMap(ParFunction fn) {
Either result = executor.getEitherSafely(label, future);
return EitherUtils.map(fn, result);
}
public NoopRequest fold(ParFunction errFn, ParFunction fn) {
return new NoopRequest<>(executor, new FoldableFuture<>(executor, future, fn, errFn));
}
/**
* The reason we need a label here is because we are creating a new ParRequest.
*/
public ParRequest map(String label, ParFunction> fn) {
return new ParRequest(label, executor, new ComposableFuture<>(executor, future, fn));
}
/**
* *
*/
public ParRequest flatMap(String label, ParFunction> fn) {
return new ParRequest(label, executor, new ComposableFutureFuture<>(executor, future, fn));
}
public Either get(long timeoutMillis) {
return executor.getEitherSafely(label, future, timeoutMillis);
}
public Either get() {
return executor.getEitherSafely(label, future);
}
ListenableFuture> asFuture() {
return future;
}
public static class Builder {
private final ParallelServiceExecutor executor;
private Option>> parCallable = Option.empty();
private boolean built = false;
private String label = "changethis";
public Builder(ParallelServiceExecutor executor) {
this.executor = executor;
}
public Builder setParCallable(ParCallable> parCallable) {
checkState(this.parCallable.isEmpty(), "Cannot set the parCallable twice!");
this.parCallable = Option.apply(parCallable);
return this;
}
public Builder with(Function1> fn1) {
checkState(this.parCallable.isEmpty(), "Cannot set the parCallable twice!");
this.parCallable = Option.apply(ParCallable.fromScala(fn1));
return this;
}
public Builder setLabel(String label) {
this.label = label;
return this;
}
public ParRequest build() {
checkState(!built, "Cannot build a request twice!");
checkState(parCallable.isDefined(), "ParCallable not defined!");
try {
ParCallable> first = ParCallable.from(parCallable.get());
return new ParRequest<>(label, executor, first);
} finally {
built = true;
}
}
}
public static ParRequest immediateResult(String label, ParallelServiceExecutor executor,
Either t) {
checkNotNull(t, "result is null");
checkNotNull(executor, "Executor is null");
return new ParRequest(label, executor, Futures.immediateFuture(t));
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy