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

com.launchdarkly.client.integrations.PersistentDataStoreBuilder Maven / Gradle / Ivy

package com.launchdarkly.client.integrations;

import com.launchdarkly.client.Components;
import com.launchdarkly.client.FeatureStoreCacheConfig;
import com.launchdarkly.client.FeatureStoreFactory;
import com.launchdarkly.client.interfaces.DiagnosticDescription;
import com.launchdarkly.client.interfaces.PersistentDataStoreFactory;

import java.util.concurrent.TimeUnit;

/**
 * A configurable factory for a persistent data store.
 * 

* Several database integrations exist for the LaunchDarkly SDK, each with its own behavior and options * specific to that database; this is described via some implementation of {@link PersistentDataStoreFactory}. * There is also universal behavior that the SDK provides for all persistent data stores, such as caching; * the {@link PersistentDataStoreBuilder} adds this. *

* After configuring this object, pass it to {@link com.launchdarkly.client.LDConfig.Builder#dataStore(FeatureStoreFactory)} * to use it in the SDK configuration. For example, using the Redis integration: * *


 *     LDConfig config = new LDConfig.Builder()
 *         .dataStore(
 *             Components.persistentDataStore(
 *                 Redis.dataStore().url("redis://my-redis-host")
 *             ).cacheSeconds(15)
 *         )
 *         .build();
 * 
* * In this example, {@code .url()} is an option specifically for the Redis integration, whereas * {@code ttlSeconds()} is an option that can be used for any persistent data store. *

* Note that this class is abstract; the actual implementation is created by calling * {@link Components#persistentDataStore(PersistentDataStoreFactory)}. * @since 4.12.0 */ @SuppressWarnings("deprecation") public abstract class PersistentDataStoreBuilder implements FeatureStoreFactory, DiagnosticDescription { /** * The default value for the cache TTL. */ public static final int DEFAULT_CACHE_TTL_SECONDS = 15; protected final PersistentDataStoreFactory persistentDataStoreFactory; protected FeatureStoreCacheConfig caching = FeatureStoreCacheConfig.DEFAULT; protected CacheMonitor cacheMonitor = null; /** * Possible values for {@link #staleValuesPolicy(StaleValuesPolicy)}. */ public enum StaleValuesPolicy { /** * Indicates that when the cache TTL expires for an item, it is evicted from the cache. The next * attempt to read that item causes a synchronous read from the underlying data store; if that * fails, no value is available. This is the default behavior. * * @see com.google.common.cache.CacheBuilder#expireAfterWrite(long, TimeUnit) */ EVICT, /** * Indicates that the cache should refresh stale values instead of evicting them. *

* In this mode, an attempt to read an expired item causes a synchronous read from the underlying * data store, like {@link #EVICT}--but if an error occurs during this refresh, the cache will * continue to return the previously cached values (if any). This is useful if you prefer the most * recently cached feature rule set to be returned for evaluation over the default value when * updates go wrong. *

* See: CacheBuilder * for more specific information on cache semantics. This mode is equivalent to {@code expireAfterWrite}. */ REFRESH, /** * Indicates that the cache should refresh stale values asynchronously instead of evicting them. *

* This is the same as {@link #REFRESH}, except that the attempt to refresh the value is done * on another thread (using a {@link java.util.concurrent.Executor}). In the meantime, the cache * will continue to return the previously cached value (if any) in a non-blocking fashion to threads * requesting the stale key. Any exception encountered during the asynchronous reload will cause * the previously cached value to be retained. *

* This setting is ideal to enable when you desire high performance reads and can accept returning * stale values for the period of the async refresh. For example, configuring this feature store * with a very low cache time and enabling this feature would see great performance benefit by * decoupling calls from network I/O. *

* See: CacheBuilder for * more specific information on cache semantics. */ REFRESH_ASYNC }; /** * Creates a new builder. * * @param persistentDataStoreFactory the factory implementation for the specific data store type */ protected PersistentDataStoreBuilder(PersistentDataStoreFactory persistentDataStoreFactory) { this.persistentDataStoreFactory = persistentDataStoreFactory; } /** * Specifies that the SDK should not use an in-memory cache for the persistent data store. * This means that every feature flag evaluation will trigger a data store query. * * @return the builder */ public PersistentDataStoreBuilder noCaching() { return cacheTime(0, TimeUnit.MILLISECONDS); } /** * Specifies the cache TTL. Items will be evicted or refreshed (depending on the StaleValuesPolicy) * after this amount of time from the time when they were originally cached. *

* If the value is zero, caching is disabled (equivalent to {@link #noCaching()}). *

* If the value is negative, data is cached forever (equivalent to {@link #cacheForever()}). * * @param cacheTime the cache TTL in whatever units you wish * @param cacheTimeUnit the time unit * @return the builder */ public PersistentDataStoreBuilder cacheTime(long cacheTime, TimeUnit cacheTimeUnit) { caching = caching.ttl(cacheTime, cacheTimeUnit); return this; } /** * Shortcut for calling {@link #cacheTime(long, TimeUnit)} with {@link TimeUnit#MILLISECONDS}. * * @param millis the cache TTL in milliseconds * @return the builder */ public PersistentDataStoreBuilder cacheMillis(long millis) { return cacheTime(millis, TimeUnit.MILLISECONDS); } /** * Shortcut for calling {@link #cacheTime(long, TimeUnit)} with {@link TimeUnit#SECONDS}. * * @param seconds the cache TTL in seconds * @return the builder */ public PersistentDataStoreBuilder cacheSeconds(long seconds) { return cacheTime(seconds, TimeUnit.SECONDS); } /** * Specifies that the in-memory cache should never expire. In this mode, data will be written * to both the underlying persistent store and the cache, but will only ever be read from * the persistent store if the SDK is restarted. *

* Use this mode with caution: it means that in a scenario where multiple processes are sharing * the database, and the current process loses connectivity to LaunchDarkly while other processes * are still receiving updates and writing them to the database, the current process will have * stale data. * * @return the builder */ public PersistentDataStoreBuilder cacheForever() { return cacheTime(-1, TimeUnit.MILLISECONDS); } /** * Specifies how the cache (if any) should deal with old values when the cache TTL expires. The default * is {@link StaleValuesPolicy#EVICT}. This property has no effect if caching is disabled. * * @param staleValuesPolicy a {@link StaleValuesPolicy} constant * @return the builder */ public PersistentDataStoreBuilder staleValuesPolicy(StaleValuesPolicy staleValuesPolicy) { caching = caching.staleValuesPolicy(FeatureStoreCacheConfig.StaleValuesPolicy.fromNewEnum(staleValuesPolicy)); return this; } /** * Provides a conduit for an application to monitor the effectiveness of the in-memory cache. *

* Create an instance of {@link CacheMonitor}; retain a reference to it, and also pass it to this * method when you are configuring the persistent data store. The store will use * {@link CacheMonitor#setSource(java.util.concurrent.Callable)} to make the caching * statistics available through that {@link CacheMonitor} instance. *

* Note that turning on cache monitoring may slightly decrease performance, due to the need to * record statistics for each cache operation. *

* Example usage: * *


   *     CacheMonitor cacheMonitor = new CacheMonitor();
   *     LDConfig config = new LDConfig.Builder()
   *         .dataStore(Components.persistentDataStore(Redis.dataStore()).cacheMonitor(cacheMonitor))
   *         .build();
   *     // later...
   *     CacheMonitor.CacheStats stats = cacheMonitor.getCacheStats();
   * 
* * @param cacheMonitor an instance of {@link CacheMonitor} * @return the builder */ public PersistentDataStoreBuilder cacheMonitor(CacheMonitor cacheMonitor) { this.cacheMonitor = cacheMonitor; return this; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy