// Copyright (C) 2019 The Android Open Source Project
//
// 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.google.gerrit.server.update;

import static java.util.Objects.requireNonNull;

import com.github.rholder.retry.RetryListener;
import com.google.common.base.Throwables;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.server.ExceptionHook;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * An action that is executed with retrying.
 *
 * <p>Instances of this class are created via {@link RetryHelper} (see {@link
 * RetryHelper#action(ActionType, String, Action)}, {@link RetryHelper#accountUpdate(String,
 * Action)}, {@link RetryHelper#changeUpdate(String, Action)}, {@link
 * RetryHelper#groupUpdate(String, Action)}, {@link RetryHelper#pluginUpdate(String, Action)}).
 *
 * <p>Which exceptions cause a retry is controlled by {@link ExceptionHook#shouldRetry(String,
 * String, Throwable)}. In addition callers can specify additional exception that should cause a
 * retry via {@link #retryOn(Predicate)}.
 */
public class RetryableAction<T> {
  /**
   * Type of an retryable action.
   *
   * <p>The action type is used for two purposes:
   *
   * <ul>
   *   <li>to determine the default timeout for executing the action (see {@link
   *       RetryHelper#getDefaultTimeout(String)})
   *   <li>as bucket for all retry metrics (see {@link RetryHelper.Metrics})
   * </ul>
   */
  public enum ActionType {
    ACCOUNT_UPDATE,
    CHANGE_UPDATE,
    GIT_UPDATE,
    GROUP_UPDATE,
    INDEX_QUERY,
    PLUGIN_UPDATE,
    REST_READ_REQUEST,
    REST_WRITE_REQUEST,
    SEND_EMAIL,
  }

  @FunctionalInterface
  public interface Action<T> {
    T call() throws Exception;
  }

  private final RetryHelper retryHelper;
  private final String actionType;
  private final Action<T> action;
  private final RetryHelper.Options.Builder options = RetryHelper.options();
  private final List<Predicate<Throwable>> exceptionPredicates = new ArrayList<>();

  private int numberOfCalls;

  RetryableAction(
      RetryHelper retryHelper, ActionType actionType, String actionName, Action<T> action) {
    this(retryHelper, requireNonNull(actionType, "actionType").name(), actionName, action);
  }

  RetryableAction(RetryHelper retryHelper, String actionType, String actionName, Action<T> action) {
    this.retryHelper = requireNonNull(retryHelper, "retryHelper");
    this.actionType = requireNonNull(actionType, "actionType");
    this.action =
        () -> {
          numberOfCalls++;
          try (TraceTimer timer =
              TraceContext.newTimer(
                  actionName, Metadata.builder().attempt(numberOfCalls).build())) {
            return requireNonNull(action, "action").call();
          }
        };
    options.actionName(requireNonNull(actionName, "actionName"));
  }

  /**
   * Adds an additional condition that should trigger retries.
   *
   * <p>For some exceptions retrying is enabled globally (see {@link
   * ExceptionHook#shouldRetry(String, String, Throwable)}). Conditions for those exceptions do not
   * need to be specified here again.
   *
   * <p>This method can be invoked multiple times to add further conditions that should trigger
   * retries.
   *
   * @param exceptionPredicate predicate that decides if the action should be retried for a given
   *     exception
   * @return this instance to enable chaining of calls
   */
  @CanIgnoreReturnValue
  public RetryableAction<T> retryOn(Predicate<Throwable> exceptionPredicate) {
    exceptionPredicates.add(exceptionPredicate);
    return this;
  }

  /**
   * Sets a condition that should trigger auto-retry with tracing.
   *
   * <p>This condition is only relevant if an exception occurs that doesn't trigger (normal) retry.
   *
   * <p>Auto-retry with tracing automatically captures traces for unexpected exceptions so that they
   * can be investigated.
   *
   * <p>Every call of this method overwrites any previously set condition for auto-retry with
   * tracing.
   *
   * @param exceptionPredicate predicate that decides if the action should be retried with tracing
   *     for a given exception
   * @return this instance to enable chaining of calls
   */
  @CanIgnoreReturnValue
  public RetryableAction<T> retryWithTrace(Predicate<Throwable> exceptionPredicate) {
    options.retryWithTrace(exceptionPredicate);
    return this;
  }

  /**
   * Sets a callback that is invoked when auto-retry with tracing is triggered.
   *
   * <p>Via the callback callers can find out with trace ID was used for the retry.
   *
   * <p>Every call of this method overwrites any previously set trace ID consumer.
   *
   * @param traceIdConsumer trace ID consumer
   * @return this instance to enable chaining of calls
   */
  @CanIgnoreReturnValue
  public RetryableAction<T> onAutoTrace(Consumer<String> traceIdConsumer) {
    options.onAutoTrace(traceIdConsumer);
    return this;
  }

  /**
   * Sets a listener that is invoked when the action is retried.
   *
   * <p>Every call of this method overwrites any previously set listener.
   *
   * @param retryListener retry listener
   * @return this instance to enable chaining of calls
   */
  @CanIgnoreReturnValue
  public RetryableAction<T> listener(RetryListener retryListener) {
    options.listener(retryListener);
    return this;
  }

  /**
   * Increases the default timeout by the given multiplier.
   *
   * <p>Every call of this method overwrites any previously set timeout.
   *
   * @param multiplier multiplier for the default timeout
   * @return this instance to enable chaining of calls
   */
  @CanIgnoreReturnValue
  public RetryableAction<T> defaultTimeoutMultiplier(int multiplier) {
    options.timeout(retryHelper.getDefaultTimeout(actionType).multipliedBy(multiplier));
    return this;
  }

  /**
   * Executes this action with retry.
   *
   * @return the result of the action
   */
  public T call() throws Exception {
    try {
      return retryHelper.execute(
          actionType,
          action,
          options.build(),
          t -> exceptionPredicates.stream().anyMatch(p -> p.test(t)));
    } catch (Exception t) {
      Throwables.throwIfUnchecked(t);
      Throwables.throwIfInstanceOf(t, Exception.class);
      throw new IllegalStateException(t);
    }
  }
}
