View Javadoc

1   package com.atlassian.vcache.internal.core.service;
2   
3   import com.atlassian.marshalling.api.MarshallingException;
4   import com.atlassian.vcache.ExternalCache;
5   import com.atlassian.vcache.ExternalCacheException;
6   import com.atlassian.vcache.internal.core.VCacheCoreUtils;
7   import org.slf4j.Logger;
8   
9   import java.time.Duration;
10  import java.util.concurrent.Callable;
11  import java.util.concurrent.CompletableFuture;
12  import java.util.concurrent.CompletionStage;
13  import java.util.concurrent.ExecutionException;
14  import java.util.function.Consumer;
15  
16  import static com.atlassian.vcache.ExternalCacheException.Reason.MARSHALLER_FAILURE;
17  import static com.atlassian.vcache.ExternalCacheException.Reason.UNCLASSIFIED_FAILURE;
18  import static com.atlassian.vcache.internal.NameValidator.requireValidCacheName;
19  import static com.atlassian.vcache.internal.core.VCacheCoreUtils.failed;
20  import static java.util.Objects.requireNonNull;
21  
22  /**
23   * Provides common operations for {@link ExternalCache} instances.
24   *
25   * @param <V> the value type
26   * @since 1.0.0
27   */
28  public abstract class AbstractExternalCache<V> implements ExternalCache<V> {
29      protected final String name;
30      protected final Duration lockTimeout;
31  
32      protected AbstractExternalCache(String name, Duration lockTimeout) {
33          this.name = requireValidCacheName(name);
34          this.lockTimeout = requireNonNull(lockTimeout);
35      }
36  
37      /**
38       * Returns the cache context for the current request.
39       *
40       * @return the cache context for the current request.
41       */
42      protected abstract AbstractExternalCacheRequestContext<V> ensureCacheContext();
43  
44      /**
45       * Returns the logging instance for the implementation class.
46       *
47       * @return the logging instance for the implementation class.
48       */
49      protected abstract Logger getLogger();
50  
51      /**
52       * Maps a generic {@link Exception} to a corresponding {@link ExternalCacheException}.
53       */
54      protected abstract ExternalCacheException mapException(Exception ex);
55  
56      @Override
57      public final String getName() {
58          return name;
59      }
60  
61      /**
62       * Performs a transaction and handles all the standard exceptions that may occur.
63       *
64       * @param txn the transaction the perform
65       * @param <T> the return type
66       * @return A {@link CompletionStage} representing the outcome of performing the transaction.
67       */
68      protected <T> CompletionStage<T> perform(Callable<T> txn) {
69          return perform(txn, (i) -> {
70          });
71      }
72  
73      /**
74       * Performs a transaction and handles all the standard exceptions that may occur.
75       *
76       * @param txn            the transaction the perform
77       * @param successHandler called if the <tt>txn</tt> is successful
78       * @param <T>            the return type
79       * @return A {@link CompletionStage} representing the outcome of performing the transaction.
80       */
81      protected <T> CompletionStage<T> perform(Callable<T> txn, Consumer<T> successHandler) {
82          try {
83              final T outcome = txn.call();
84              successHandler.accept(outcome);
85              return VCacheCoreUtils.successful(outcome);
86          } catch (MarshallingException ex) {
87              return failed(new CompletableFuture<>(), new ExternalCacheException(MARSHALLER_FAILURE, ex));
88          } catch (ExecutionException | InterruptedException ex) {
89              return failed(new CompletableFuture<>(), new ExternalCacheException(UNCLASSIFIED_FAILURE, ex));
90          } catch (ExternalCacheException ece) {
91              return failed(new CompletableFuture<>(), ece);
92          } catch (Exception ex) {
93              return failed(new CompletableFuture<>(), mapException(ex));
94          }
95      }
96  }