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

com.fitbur.failsafe.Callables Maven / Gradle / Ivy

The newest version!
package com.fitbur.failsafe;

import java.util.concurrent.Callable;
import java.util.concurrent.Semaphore;
import java.util.function.BiConsumer;

import com.fitbur.failsafe.event.ContextualResultListener;
import com.fitbur.failsafe.event.FailureListener;
import com.fitbur.failsafe.event.ResultListener;
import com.fitbur.failsafe.function.AsyncCallable;
import com.fitbur.failsafe.function.AsyncRunnable;
import com.fitbur.failsafe.function.CheckedRunnable;
import com.fitbur.failsafe.function.ContextualCallable;
import com.fitbur.failsafe.function.ContextualRunnable;
import com.fitbur.failsafe.internal.util.Assert;

/**
 * Utility for creating callables.
 * 
 * @author Jonathan Halterman
 */
final class Callables {
  static abstract class ContextualCallableWrapper implements Callable {
    protected ExecutionContext context;

    void inject(ExecutionContext context) {
      this.context = context;
    }
  }

  static abstract class AsyncCallableWrapper implements Callable {
    protected AsyncExecution execution;

    void inject(AsyncExecution execution) {
      this.execution = execution;
    }
  }

  static  Callable of(final ContextualResultListener listener, final T result,
      final Throwable failure, final ExecutionContext context) {
    return new Callable() {
      @Override
      public T call() {
        listener.onResult(result, failure, context);
        return null;
      }
    };
  }

  static  Callable of(final FailureListener listener, final Throwable failure) {
    return new Callable() {
      @Override
      public T call() {
        listener.onFailure(failure);
        return null;
      }
    };
  }

  static  Callable of(final ResultListener listener, final T result, final Throwable failure) {
    return new Callable() {
      @Override
      public T call() {
        listener.onResult(result, failure);
        return null;
      }
    };
  }

  static  Callable of(final CheckedRunnable runnable) {
    Assert.notNull(runnable, "runnable");
    return new Callable() {
      @Override
      public T call() throws Exception {
        runnable.run();
        return null;
      }
    };
  }

  static  Callable of(final ContextualCallable callable) {
    Assert.notNull(callable, "callable");
    return new ContextualCallableWrapper() {
      @Override
      public T call() throws Exception {
        T result = callable.call(context);
        return result;
      }
    };
  }

  static  Callable of(final ContextualRunnable runnable) {
    Assert.notNull(runnable, "runnable");
    return new ContextualCallableWrapper() {
      @Override
      public T call() throws Exception {
        runnable.run(context);
        return null;
      }
    };
  }

  static  AsyncCallableWrapper asyncOf(final AsyncCallable callable) {
    Assert.notNull(callable, "callable");
    return new AsyncCallableWrapper() {
      @Override
      public synchronized T call() throws Exception {
        try {
          execution.before();
          T result = callable.call(execution);
          return result;
        } catch (Exception e) {
          execution.completeOrRetry(null, e);
          return null;
        }
      }
    };
  }

  static  AsyncCallableWrapper asyncOf(final AsyncRunnable runnable) {
    Assert.notNull(runnable, "runnable");
    return new AsyncCallableWrapper() {
      @Override
      public synchronized T call() throws Exception {
        try {
          execution.before();
          runnable.run(execution);
        } catch (Exception e) {
          execution.completeOrRetry(null, e);
        }

        return null;
      }
    };
  }

  static  AsyncCallableWrapper asyncOf(final Callable callable) {
    Assert.notNull(callable, "callable");
    return new AsyncCallableWrapper() {
      @Override
      public T call() throws Exception {
        try {
          execution.before();
          T result = callable.call();
          execution.completeOrRetry(result, null);
          return result;
        } catch (Exception e) {
          execution.completeOrRetry(null, e);
          return null;
        }
      }
    };
  }

  static  AsyncCallableWrapper asyncOf(final CheckedRunnable runnable) {
    Assert.notNull(runnable, "runnable");
    return new AsyncCallableWrapper() {
      @Override
      public T call() throws Exception {
        try {
          execution.before();
          runnable.run();
          execution.completeOrRetry(null, null);
        } catch (Exception e) {
          execution.completeOrRetry(null, e);
        }

        return null;
      }
    };
  }

  static  AsyncCallableWrapper asyncOf(final ContextualCallable callable) {
    Assert.notNull(callable, "callable");
    return new AsyncCallableWrapper() {
      @Override
      public T call() throws Exception {
        try {
          execution.before();
          T result = callable.call(execution);
          execution.completeOrRetry(result, null);
          return result;
        } catch (Exception e) {
          execution.completeOrRetry(null, e);
          return null;
        }
      }
    };
  }

  static  AsyncCallableWrapper asyncOf(final ContextualRunnable runnable) {
    Assert.notNull(runnable, "runnable");
    return new AsyncCallableWrapper() {
      @Override
      public T call() throws Exception {
        try {
          execution.before();
          runnable.run(execution);
          execution.completeOrRetry(null, null);
        } catch (Exception e) {
          execution.completeOrRetry(null, e);
        }

        return null;
      }
    };
  }

  static  AsyncCallableWrapper ofFuture(final AsyncCallable> callable) {
    Assert.notNull(callable, "callable");
    return new AsyncCallableWrapper() {
      Semaphore asyncFutureLock = new Semaphore(1);

      @Override
      public T call() throws Exception {
        try {
          execution.before();
          asyncFutureLock.acquire();
          callable.call(execution).whenComplete(new BiConsumer() {
            @Override
            public void accept(T innerResult, Throwable failure) {
              try {
                if (failure != null)
                  execution.completeOrRetry(innerResult,
                      failure instanceof java.util.concurrent.CompletionException ? failure.getCause() : failure);
              } finally {
                asyncFutureLock.release();
              }
            }
          });
        } catch (Exception e) {
          try {
            execution.completeOrRetry(null, e);
          } finally {
            asyncFutureLock.release();
          }
        }

        return null;
      }
    };
  }

  static  AsyncCallableWrapper ofFuture(final Callable> callable) {
    Assert.notNull(callable, "callable");
    return new AsyncCallableWrapper() {
      @Override
      public T call() throws Exception {
        try {
          execution.before();
          callable.call().whenComplete(new BiConsumer() {
            @Override
            public void accept(T innerResult, Throwable failure) {
              // Unwrap CompletionException cause
              if (failure != null && failure instanceof java.util.concurrent.CompletionException)
                failure = failure.getCause();
              execution.completeOrRetry(innerResult, failure);
            }
          });
        } catch (Exception e) {
          execution.completeOrRetry(null, e);
        }

        return null;
      }
    };
  }

  static  AsyncCallableWrapper ofFuture(
      final ContextualCallable> callable) {
    Assert.notNull(callable, "callable");
    return new AsyncCallableWrapper() {
      @Override
      public T call() throws Exception {
        try {
          execution.before();
          callable.call(execution).whenComplete(new BiConsumer() {
            @Override
            public void accept(T innerResult, Throwable failure) {
              // Unwrap CompletionException cause
              if (failure != null && failure instanceof java.util.concurrent.CompletionException)
                failure = failure.getCause();
              execution.completeOrRetry(innerResult, failure);
            }
          });
        } catch (Exception e) {
          execution.completeOrRetry(null, e);
        }

        return null;
      }
    };
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy