All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yahoo.maha.parrequest2.future.ParRequest2 Maven / Gradle / Ivy

There is a newer version: 6.158
Show newest version
// 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