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

com.yahoo.maha.parrequest2.future.ParRequest5 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 com.yahoo.maha.parrequest2.GeneralError;
import scala.Option;
import scala.Tuple5;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

/**
 * This class represents five parallel requests which can be composed synchronously with resultMap, or composed
 * asynchronously with map and fold
 */
public class ParRequest5 extends CombinableRequest> {

    private final ParallelServiceExecutor executor;
    private final CombinedFuture5 combinedFuture5;

    ParRequest5(String label, ParallelServiceExecutor executor,
                ParCallable> firstRequest,
                ParCallable> secondRequest,
                ParCallable> thirdRequest,
                ParCallable> fourthRequest,
                ParCallable> fifthRequest) {
        checkNotNull(executor, "Executor is null");
        checkNotNull(firstRequest, "First request is null");
        checkNotNull(secondRequest, "Second request is null");
        checkNotNull(thirdRequest, "Third request is null");
        checkNotNull(fourthRequest, "Fourth request is null");
        checkNotNull(fifthRequest, "Fifth 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);
        final ListenableFuture> fourthFuture = executor.submitParCallable(fourthRequest);
        final ListenableFuture> fifthFuture = executor.submitParCallable(fifthRequest);

        try {
            combinedFuture5 = CombinedFuture5.from(executor, firstFuture, secondFuture, thirdFuture, fourthFuture, fifthFuture);
        } catch (Exception e) {
            //failed to create combiner, cancel futures and re-throw exception
            firstFuture.cancel(false);
            secondFuture.cancel(false);
            thirdFuture.cancel(false);
            fourthFuture.cancel(false);
            fifthFuture.cancel(false);
            throw e;
        }
    }

    ParRequest5(String label, ParallelServiceExecutor executor,
                CombinableRequest firstRequest,
                CombinableRequest secondRequest,
                CombinableRequest thirdRequest,
                CombinableRequest fourthRequest,
                CombinableRequest fifthRequest) {
        checkNotNull(executor, "Executor is null");
        checkNotNull(firstRequest, "First request is null");
        checkNotNull(secondRequest, "Second request is null");
        checkNotNull(thirdRequest, "Third request is null");
        checkNotNull(fourthRequest, "Fourth request is null");
        checkNotNull(fifthRequest, "Fifth request is null");
        this.label = label;
        this.executor = executor;
        combinedFuture5 = CombinedFuture5.from(
                executor, firstRequest.asFuture(), secondRequest.asFuture(), thirdRequest.asFuture(), fourthRequest.asFuture(), fifthRequest.asFuture());
    }

    public  Either resultMap(ParFunction, O> fn) {
        Either> result = executor.getEitherSafely(label, combinedFuture5);
        return EitherUtils.map(fn, result);
    }

    public  NoopRequest fold(ParFunction errFn, ParFunction, O> fn) {
        return new NoopRequest(executor, new FoldableFuture<>(executor, combinedFuture5, fn, errFn));
    }

    public  ParRequest map(String label, ParFunction, Either> fn) {
        return new ParRequest<>(label, executor, new ComposableFuture<>(executor, combinedFuture5, fn));
    }

    public  ParRequest flatMap(String label, ParFunction, CombinableRequest> fn) {
        return new ParRequest<>(label, executor, new ComposableFutureFuture<>(executor, combinedFuture5, fn));
    }

    public Either> get() {
        return executor.getEitherSafely(label, combinedFuture5);
    }

    ListenableFuture>> asFuture() {
        return combinedFuture5;
    }

    public static class Builder {

        private final ParallelServiceExecutor executor;
        private Option>> firstParCallable = Option.empty();
        private Option>> secondParCallable = Option.empty();
        private Option>> thirdParCallable = Option.empty();
        private Option>> fourthParCallable = Option.empty();
        private Option>> fifthParCallable = Option.empty();
        private boolean built = 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 setFourthParCallable(ParCallable> parCallable) {
            checkState(fourthParCallable.isEmpty(), "Cannot set the fourth parCallable twice!");
            fourthParCallable = Option.apply(parCallable);
            return this;
        }

        public Builder setFifthParCallable(ParCallable> parCallable) {
            checkState(fifthParCallable.isEmpty(), "Cannot set the fifth parCallable twice!");
            fifthParCallable = Option.apply(parCallable);
            return this;
        }

        public ParRequest5 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!");
            checkState(fourthParCallable.isDefined(), "Fourth parCallable not defined!");
            checkState(fifthParCallable.isDefined(), "Fifth parCallable not defined!");
            try {
                ParCallable> first = ParCallable.from(firstParCallable.get());
                ParCallable> second = ParCallable.from(secondParCallable.get());
                ParCallable> third = ParCallable.from(thirdParCallable.get());
                ParCallable> fourth = ParCallable.from(fourthParCallable.get());
                ParCallable> fifth = ParCallable.from(fifthParCallable.get());
                return new ParRequest5<>(label, executor, first, second, third, fourth, fifth);
            } finally {
                built = true;
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy