class FallbackExecutor<R> extends PolicyExecutor<R> {
  private final FallbackImpl<R> fallback;
  private final FallbackConfig<R> config;
  private final EventHandler<R> failedAttemptHandler;

  public FallbackExecutor(FallbackImpl<R> fallback, int policyIndex) {
    super(fallback, policyIndex);
    this.fallback = fallback;
    this.config = fallback.getConfig();
    this.failedAttemptHandler = EventHandler.ofExecutionAttempted(config.getFailedAttemptListener());
  }

  /**
   * Performs an execution by applying the {@code innerFn}, applying a fallback if it fails, and calling post-execute.
   */
  @Override
  public Function<SyncExecutionInternal<R>, ExecutionResult<R>> apply(
    Function<SyncExecutionInternal<R>, ExecutionResult<R>> innerFn, Scheduler scheduler) {<FILL_FUNCTION_BODY>}

  /**
   * Performs an async execution by applying the {@code innerFn}, applying a fallback if it fails, and calling
   * post-execute.
   */
  @Override
  public Function<AsyncExecutionInternal<R>, CompletableFuture<ExecutionResult<R>>> applyAsync(
    Function<AsyncExecutionInternal<R>, CompletableFuture<ExecutionResult<R>>> innerFn, Scheduler scheduler,
    FailsafeFuture<R> future) {

    return execution -> innerFn.apply(execution).thenCompose(result -> {
      if (result == null || future.isDone())
        return ExecutionResult.nullFuture();
      if (execution.isCancelled(this))
        return CompletableFuture.completedFuture(result);
      if (!isFailure(result))
        return postExecuteAsync(execution, result, scheduler, future);

      if (failedAttemptHandler != null)
        failedAttemptHandler.handle(result, execution);

      CompletableFuture<ExecutionResult<R>> promise = new CompletableFuture<>();
      Callable<R> callable = () -> {
        try {
          CompletableFuture<R> fallbackFuture = fallback.applyStage(result.getResult(), result.getException(),
            execution);
          fallbackFuture.whenComplete((innerResult, exception) -> {
            if (exception instanceof CompletionException)
              exception = exception.getCause();
            ExecutionResult<R> r =
              exception == null ? result.withResult(innerResult) : ExecutionResult.exception(exception);
            promise.complete(r);
          });
        } catch (Throwable t) {
          promise.complete(ExecutionResult.exception(t));
        }
        return null;
      };

      try {
        if (!config.isAsync())
          callable.call();
        else {
          Future<?> scheduledFallback = scheduler.schedule(callable, 0, TimeUnit.NANOSECONDS);

          // Propagate outer cancellations to the Fallback future and its promise
          future.setCancelFn(this, (mayInterrupt, cancelResult) -> {
            scheduledFallback.cancel(mayInterrupt);
            promise.complete(cancelResult);
          });
        }
      } catch (Throwable t) {
        // Hard scheduling failure
        promise.completeExceptionally(t);
      }

      return promise.thenCompose(ss -> postExecuteAsync(execution, ss, scheduler, future));
    });
  }
}


    return execution -> {
      ExecutionResult<R> result = innerFn.apply(execution);
      if (execution.isCancelled(this))
        return result;

      if (isFailure(result)) {
        if (failedAttemptHandler != null)
          failedAttemptHandler.handle(result, execution);

        try {
          result = fallback == FallbackImpl.NONE ?
            result.withNonResult() :
            result.withResult(fallback.apply(result.getResult(), result.getException(), execution));
        } catch (Throwable t) {
          result = ExecutionResult.exception(t);
        }
      }

      return postExecute(execution, result);
    };
  
<methods>public Function<SyncExecutionInternal<R>,ExecutionResult<R>> apply(Function<SyncExecutionInternal<R>,ExecutionResult<R>>, dev.failsafe.spi.Scheduler) ,public Function<AsyncExecutionInternal<R>,CompletableFuture<ExecutionResult<R>>> applyAsync(Function<AsyncExecutionInternal<R>,CompletableFuture<ExecutionResult<R>>>, dev.failsafe.spi.Scheduler, FailsafeFuture<R>) ,public int getPolicyIndex() ,public ExecutionResult<R> postExecute(ExecutionInternal<R>, ExecutionResult<R>) <variables>private final non-sealed EventHandler<R> failureHandler,private final non-sealed FailurePolicy<R> failurePolicy,private final non-sealed int policyIndex,private final non-sealed EventHandler<R> successHandler