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

com.dyngr.PollerBuilder Maven / Gradle / Ivy

There is a newer version: 1.1.3
Show newest version
/*
 * Copyright 2012-2015 Ye Ding
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.dyngr;

import java.util.concurrent.ExecutorService;

import com.dyngr.concurrent.DirectExecutorService;
import com.dyngr.core.Attempt;
import com.dyngr.core.AttemptMaker;
import com.dyngr.core.DefaultPoller;
import com.dyngr.core.StopStrategies;
import com.dyngr.core.StopStrategy;
import com.dyngr.core.WaitStrategies;
import com.dyngr.core.WaitStrategy;
import com.dyngr.util.Preconditions;

/**
 * A builder to build a {@link Poller}.
 *
 * @param  result type of {@link Poller}'s polling for.
 * @author dingye
 */
public class PollerBuilder {
    private AttemptMaker attemptMaker;
    private Boolean         stopIfException;
    private StopStrategy    stopStrategy;
    private WaitStrategy    waitStrategy;
    private ExecutorService executorService;

    /**
     * Sets the wait strategy used to decide how long to sleep between failed attempts.
     * The default strategy is to retry immediately after a failed attempt.
     *
     * @param waitStrategy the strategy used to sleep between failed attempts
     * @return this
     * @throws IllegalStateException if a wait strategy has already been set.
     */
    public PollerBuilder withWaitStrategy(WaitStrategy waitStrategy) {
        Preconditions.checkNotNull(waitStrategy, "waitStrategy should not be null");
        Preconditions.checkState(this.waitStrategy == null, "a waitStrategy has already been set %s", this.waitStrategy);
        this.waitStrategy = waitStrategy;
        return this;
    }

    /**
     * Sets a list of wait strategy used to decide how long to sleep between failed attempts. Actual wait time will be a total of all computed wait time.
     *
     * @param waitStrategies list of strategies used to sleep between failed attempts
     * @return this
     * @throws IllegalStateException if a wait strategy has already been set.
     */
    public PollerBuilder withWaitStrategy(WaitStrategy... waitStrategies) {
        Preconditions.checkNotNull(waitStrategies, "waitStrategy should not be null");
        for (WaitStrategy strategy : waitStrategies) {
            Preconditions.checkNotNull(strategy, "waitStrategy should not be null");
        }
        this.waitStrategy = WaitStrategies.join(waitStrategies);
        return this;
    }

    /**
     * Set if poller should stop when an exception is thrown. The default value is true.
     *
     * @param stopIfException whether poller should stop if exception occurred
     * @return this
     */
    public PollerBuilder stopIfException(boolean stopIfException) {
        this.stopIfException = stopIfException;
        return this;
    }

    /**
     * Sets the stop strategy used to decide when to stop retrying. The default strategy is to not stop at all .
     *
     * @param stopStrategy the strategy used to decide when to stop retrying
     * @return this
     * @throws IllegalStateException if a stop strategy has already been set.
     */
    public PollerBuilder withStopStrategy(StopStrategy stopStrategy) {
        Preconditions.checkNotNull(stopStrategy, "stopStrategy should not be null");
        Preconditions.checkState(this.stopStrategy == null, "a stopStrategy has already been set %s", this.stopStrategy);
        this.stopStrategy = stopStrategy;
        return this;
    }

    /**
     * Sets a list of stop strategies used to decide when to stop retrying. polling will stop if any stop strategy's condition is fulfilled.
     *
     * @param stopStrategies list of strategies used to decide when to stop retrying.
     * @return this
     * @throws IllegalStateException if a stop strategy has already been set.
     */
    public PollerBuilder withStopStrategy(StopStrategy... stopStrategies) {
        Preconditions.checkState(this.stopStrategy == null, "a stopStrategy has already been set %s", this.stopStrategy);
        for (StopStrategy strategy : stopStrategies) {
            Preconditions.checkNotNull(strategy, "stopStrategy should not be null");
        }
        this.stopStrategy = StopStrategies.join(stopStrategies);
        return this;
    }

    /**
     * Sets the {@link ExecutorService} on which {@link Poller} will be running. The default is on the thread that calls {@link Poller#start()}.
     *
     * @param executorService the executor service which is used to do the polling.
     * @return this
     * @throws IllegalStateException if an executor service has already been set.
     */
    public PollerBuilder withExecutorService(ExecutorService executorService) {
        Preconditions.checkNotNull(executorService, "executorService should not be null");
        Preconditions.checkState(this.executorService == null, "a executorService has already been set %s", this.executorService);
        this.executorService = executorService;
        return this;
    }

    /**
     * Sets the code of actual polling.
     *
     * @param attemptMaker the polling body.
     * @return this
     * @throws IllegalArgumentException if an attempt maker has already been set.
     */
    public PollerBuilder polling(AttemptMaker attemptMaker) {
        Preconditions.checkNotNull(attemptMaker, "attemptMake should not be null");
        Preconditions.checkState(this.attemptMaker == null, "a attemptMake has already been set %s", this.attemptMaker);
        this.attemptMaker = attemptMaker;
        return this;
    }

    /**
     * Finally build the {@link Poller} instance.
     *
     * @return the built poller.
     */
    public Poller build() {
        Preconditions.checkNotNull(attemptMaker, "attemptMaker should not be null, please call polling() to add a AttemptMaker");
        return new DefaultPoller(
                attemptMaker,
                buildStopStrategy(),
                waitStrategy == null ? WaitStrategies.noWait() : waitStrategy,
                executorService == null ? new DirectExecutorService() : executorService
        );
    }

    /**
     * Constructs a new builder
     *
     * @param  result type of {@link Poller}'s polling for.
     * @return the new builder
     */
    public static  PollerBuilder newBuilder() {
        return new PollerBuilder();
    }

    /**
     * Build a stop strategy based on user defined ones.
     */
    private StopStrategy buildStopStrategy() {
        if (stopStrategy == null) {
            stopStrategy = StopStrategies.neverStop();
        }

        if (stopIfException == null) {
            stopIfException = true;
        }

        return new MayStopIfExceptionStopStrategy(stopIfException, stopStrategy);
    }

    /**
     * A wrapper stop strategy that may or may not stop if exception occurred.
     */
    private static class MayStopIfExceptionStopStrategy implements StopStrategy {
        private final boolean stopIfException;
        private final StopStrategy stopStrategy;

        public MayStopIfExceptionStopStrategy(boolean stopIfException, StopStrategy stopStrategy) {
            this.stopIfException = stopIfException;
            this.stopStrategy = stopStrategy;
        }

        @Override
        public boolean shouldStop(Attempt failedAttempt) {
            if (stopIfException && failedAttempt.hasException()) {
                return true;
            } else {
                return stopStrategy.shouldStop(failedAttempt);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy