View Javadoc

1   package com.atlassian.vcache.internal.memcached;
2   
3   import com.atlassian.vcache.internal.BegunTransactionalActivityHandler;
4   import com.atlassian.vcache.internal.ExternalCacheExceptionListener;
5   import com.atlassian.vcache.internal.RequestContext;
6   import com.atlassian.vcache.internal.VCacheCreationHandler;
7   import com.atlassian.vcache.internal.VCacheSettingsDefaultsProvider;
8   import com.atlassian.vcache.internal.core.ExternalCacheKeyGenerator;
9   import com.atlassian.vcache.internal.core.Sha1ExternalCacheKeyGenerator;
10  import com.atlassian.vcache.internal.core.metrics.DefaultMetricsCollector;
11  import com.atlassian.vcache.internal.core.metrics.MetricsCollector;
12  import net.spy.memcached.MemcachedClientIF;
13  
14  import java.time.Duration;
15  import java.util.function.Function;
16  import java.util.function.Supplier;
17  
18  import static java.util.Objects.requireNonNull;
19  
20  /**
21   * Builder for creating {@link MemcachedVCacheServiceSettings} instances.
22   * <p>
23   * All settings must be set before {@link #build()} can be called, except for
24   * {@link #metricsCollector(MetricsCollector)}, {@link #begunTransactionalActivityHandler(BegunTransactionalActivityHandler)}
25   * and {@link #dontExternaliseCache(Function)}. See their Javadoc for the defaults used.
26   * </p>
27   * <p>
28   * Either {@link #externalCacheKeyGenerator(ExternalCacheKeyGenerator)} or {@link #productIdentifier(String)} must be
29   * called.
30   * </p>
31   *
32   * @since 1.3.0
33   */
34  public class MemcachedVCacheServiceSettingsBuilder {
35      private Supplier<MemcachedClientIF> clientSupplier;
36      private Supplier<RequestContext> threadLocalContextSupplier;
37      private Supplier<RequestContext> workContextContextSupplier;
38      private VCacheSettingsDefaultsProvider defaultsProvider;
39      private VCacheCreationHandler creationHandler;
40      private MetricsCollector metricsCollector;
41      private ExternalCacheKeyGenerator externalCacheKeyGenerator;
42      // By default, don't care
43      private BegunTransactionalActivityHandler begunTransactionalActivityHandler = context -> {
44      };
45      // By default, externalise the external caches.
46      private Function<String, Boolean> dontExternaliseCache = name -> false;
47      // By default, don't use this hack
48      private boolean serializationHack;
49      // By default, wait a fixed time
50      @SuppressWarnings("checkstyle:MagicNumber")
51      private Duration lockTimeout = Duration.ofSeconds(30);
52      // By default, don't care about listening
53      private ExternalCacheExceptionListener externalCacheExceptionListener = (n, ex) -> {};
54  
55      /**
56       * Sets the client supplier.
57       *
58       * @param clientSupplier the client supplier.
59       * @return the builder
60       */
61      public MemcachedVCacheServiceSettingsBuilder clientSupplier(Supplier<MemcachedClientIF> clientSupplier) {
62          this.clientSupplier = requireNonNull(clientSupplier);
63          return this;
64      }
65  
66      /**
67       * Sets the context supplier.
68       *
69       * @param threadLocalContextSupplier the context supplier.
70       * @return the builder.
71       */
72      public MemcachedVCacheServiceSettingsBuilder threadLocalContextSupplier(Supplier<RequestContext> threadLocalContextSupplier) {
73          this.threadLocalContextSupplier = requireNonNull(threadLocalContextSupplier);
74          return this;
75      }
76  
77      /**
78       * Sets the context supplier for caches that can be thread safe.
79       *
80       * @param contextSupplier the context supplier.
81       * @return the builder.
82       */
83      public MemcachedVCacheServiceSettingsBuilder workContextContextSupplier(Supplier<RequestContext> contextSupplier) {
84          this.workContextContextSupplier = contextSupplier;
85          return this;
86      }
87  
88      /**
89       * Sets the defaults provider.
90       *
91       * @param defaultsProvider the defaults provider.
92       * @return the builder.
93       */
94      public MemcachedVCacheServiceSettingsBuilder defaultsProvider(VCacheSettingsDefaultsProvider defaultsProvider) {
95          this.defaultsProvider = requireNonNull(defaultsProvider);
96          return this;
97      }
98  
99      /**
100      * Set the creation handler.
101      *
102      * @param creationHandler the creation handler.
103      * @return the builder.
104      */
105     public MemcachedVCacheServiceSettingsBuilder creationHandler(VCacheCreationHandler creationHandler) {
106         this.creationHandler = requireNonNull(creationHandler);
107         return this;
108     }
109 
110     /**
111      * Sets the metrics collector. If not invoked, then the {@link DefaultMetricsCollector} implementation will be
112      * used.
113      *
114      * @param metricsCollector the metrics collector.
115      * @return the builder.
116      */
117     public MemcachedVCacheServiceSettingsBuilder metricsCollector(MetricsCollector metricsCollector) {
118         this.metricsCollector = requireNonNull(metricsCollector);
119         return this;
120     }
121 
122     /**
123      * Equivalent to calling {@link #externalCacheKeyGenerator(ExternalCacheKeyGenerator)} passing a
124      * {@link Sha1ExternalCacheKeyGenerator} instance created using the supplied product identifier.
125      *
126      * @param productIdentifier the product identifier to use with the {@link Sha1ExternalCacheKeyGenerator}.
127      * @return the builder.
128      */
129     public MemcachedVCacheServiceSettingsBuilder productIdentifier(String productIdentifier) {
130         this.externalCacheKeyGenerator = new Sha1ExternalCacheKeyGenerator(productIdentifier);
131         return this;
132     }
133 
134     /**
135      * Set the external cache key generator.
136      *
137      * @param externalCacheKeyGenerator the external cache key generator.
138      * @return the builder.
139      */
140     public MemcachedVCacheServiceSettingsBuilder externalCacheKeyGenerator(ExternalCacheKeyGenerator externalCacheKeyGenerator) {
141         this.externalCacheKeyGenerator = requireNonNull(externalCacheKeyGenerator);
142         return this;
143     }
144 
145     /**
146      * Sets the begun transaction activity handler. If not invoked, then a default implementation is provided that does
147      * nothing.
148      *
149      * @param handler the begun transaction activity handler.
150      * @return the builder.
151      */
152     public MemcachedVCacheServiceSettingsBuilder begunTransactionalActivityHandler(BegunTransactionalActivityHandler handler) {
153         this.begunTransactionalActivityHandler = requireNonNull(handler);
154         return this;
155     }
156 
157     /**
158      * Sets the function to determine whether an {@link com.atlassian.vcache.ExternalCache} should really be externalised.
159      * If the supplied function returns <tt>true</tt> for a cache, then an in-memory implementation will be used.
160      * <p>
161      * If not set, then a default implementation is provided that will externalise all {@link com.atlassian.vcache.ExternalCache}'s.
162      * nothing.
163      * </p>
164      * <p>
165      * Note: this function is provided to allow for an orderly migration of external caches from being in-memory
166      * to be stored in Memcached.
167      * </p>
168      *
169      * @param dontExternaliseCache the function to determine whether an {@link com.atlassian.vcache.ExternalCache}
170      *                                 should really be externalised.
171      * @return the builder.
172      */
173     public MemcachedVCacheServiceSettingsBuilder dontExternaliseCache(Function<String, Boolean> dontExternaliseCache) {
174         this.dontExternaliseCache = requireNonNull(dontExternaliseCache);
175         return this;
176     }
177 
178     /**
179      * Enable the serialization hack, whereby if an {@link com.atlassian.vcache.ExternalCache}'s values are
180      * {@link java.io.Serializable}, then the values are not marshalled before they are passed to the delegate
181      * Atlassian Cache. This is to allow for performance optimisations.
182      */
183     public MemcachedVCacheServiceSettingsBuilder enableSerializationHack() {
184         serializationHack = true;
185         return this;
186     }
187 
188     /**
189      * Change the timeout that is used when acquiring locks.
190      * @param lockTimeout the timeout that is used when acquiring locks.
191      * @return the current builder
192      */
193     public MemcachedVCacheServiceSettingsBuilder lockTimeout(Duration lockTimeout) {
194         this.lockTimeout = requireNonNull(lockTimeout);
195         return this;
196     }
197 
198     /**
199      * Set the external cache exception listener.
200      *
201      * @param externalCacheExceptionListener the external cache exception listener.
202      * @return the builder.
203      */
204     public MemcachedVCacheServiceSettingsBuilder externalCacheExceptionListener(ExternalCacheExceptionListener externalCacheExceptionListener) {
205         this.externalCacheExceptionListener = requireNonNull(externalCacheExceptionListener);
206         return this;
207     }
208 
209     /**
210      * Returns a new {@link MemcachedVCacheServiceSettings} instance configured using the supplied settings.
211      *
212      * @return a new {@link MemcachedVCacheServiceSettings} instance configured using the supplied settings.
213      */
214     public MemcachedVCacheServiceSettings build() {
215         return new MemcachedVCacheServiceSettings(
216                 requireNonNull(clientSupplier, "missing clientSupplier"),
217                 requireNonNull(threadLocalContextSupplier, "missing threadLocalContextSupplier"),
218                 requireNonNull(workContextContextSupplier, "missing thread safe workContextContextSupplier"),
219                 requireNonNull(defaultsProvider, "missing defaultsProvider"),
220                 requireNonNull(creationHandler, "missing creationHandler"),
221                 (metricsCollector != null) ? metricsCollector : new DefaultMetricsCollector(threadLocalContextSupplier),
222                 requireNonNull(externalCacheKeyGenerator, "missing externalCacheKeyGenerator"),
223                 begunTransactionalActivityHandler,
224                 dontExternaliseCache,
225                 serializationHack,
226                 lockTimeout,
227                 externalCacheExceptionListener);
228     }
229 }