
com.launchdarkly.sdk.server.integrations.RedisDataStoreImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of launchdarkly-java-server-sdk-redis-store Show documentation
Show all versions of launchdarkly-java-server-sdk-redis-store Show documentation
LaunchDarkly Java SDK Redis integration
package com.launchdarkly.sdk.server.integrations;
import com.launchdarkly.sdk.server.interfaces.DataStoreTypes.DataKind;
import com.launchdarkly.sdk.server.interfaces.DataStoreTypes.FullDataSet;
import com.launchdarkly.sdk.server.interfaces.DataStoreTypes.ItemDescriptor;
import com.launchdarkly.sdk.server.interfaces.DataStoreTypes.KeyedItems;
import com.launchdarkly.sdk.server.interfaces.DataStoreTypes.SerializedItemDescriptor;
import com.launchdarkly.sdk.server.interfaces.PersistentDataStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Transaction;
import redis.clients.util.JedisURIHelper;
final class RedisDataStoreImpl implements PersistentDataStore {
private static final Logger logger = LoggerFactory.getLogger(RedisDataStoreImpl.class);
private final JedisPool pool;
private final String prefix;
private UpdateListener updateListener;
RedisDataStoreImpl(RedisDataStoreBuilder builder) {
// There is no builder for JedisPool, just a large number of constructor overloads. Unfortunately,
// the overloads that accept a URI do not accept the other parameters we need to set, so we need
// to decompose the URI.
String host = builder.uri.getHost();
int port = builder.uri.getPort();
String password = builder.password == null ? JedisURIHelper.getPassword(builder.uri) : builder.password;
int database = builder.database == null ? JedisURIHelper.getDBIndex(builder.uri): builder.database.intValue();
boolean tls = builder.tls || builder.uri.getScheme().equals("rediss");
String extra = tls ? " with TLS" : "";
if (password != null) {
extra = extra + (extra.isEmpty() ? " with" : " and") + " password";
}
logger.info(String.format("Connecting to Redis feature store at %s:%d/%d%s", host, port, database, extra));
JedisPoolConfig poolConfig = (builder.poolConfig != null) ? builder.poolConfig : new JedisPoolConfig();
JedisPool pool = new JedisPool(poolConfig,
host,
port,
(int)builder.connectTimeout.toMillis(),
(int)builder.socketTimeout.toMillis(),
password,
database,
null, // clientName
tls,
null, // sslSocketFactory
null, // sslParameters
null // hostnameVerifier
);
String prefix = (builder.prefix == null || builder.prefix.isEmpty()) ?
RedisDataStoreBuilder.DEFAULT_PREFIX :
builder.prefix;
this.pool = pool;
this.prefix = prefix;
}
@Override
public SerializedItemDescriptor get(DataKind kind, String key) {
try (Jedis jedis = pool.getResource()) {
String item = getRedis(kind, key, jedis);
return item == null ? null : new SerializedItemDescriptor(0, false, item);
}
}
@Override
public KeyedItems getAll(DataKind kind) {
try (Jedis jedis = pool.getResource()) {
Map allJson = jedis.hgetAll(itemsKey(kind));
List> itemsOut = new ArrayList<>(allJson.size());
for (Map.Entry e: allJson.entrySet()) {
itemsOut.add(new AbstractMap.SimpleEntry<>(e.getKey(), new SerializedItemDescriptor(0, false, e.getValue())));
}
return new KeyedItems<>(itemsOut);
}
}
@Override
public void init(FullDataSet allData) {
try (Jedis jedis = pool.getResource()) {
Transaction t = jedis.multi();
for (Map.Entry> e0: allData.getData()) {
DataKind kind = e0.getKey();
String baseKey = itemsKey(kind);
t.del(baseKey);
for (Map.Entry e1: e0.getValue().getItems()) {
t.hset(baseKey, e1.getKey(), jsonOrPlaceholder(kind, e1.getValue()));
}
}
t.set(initedKey(), "");
t.exec();
}
}
@Override
public boolean upsert(DataKind kind, String key, SerializedItemDescriptor newItem) {
while (true) {
Jedis jedis = null;
try {
jedis = pool.getResource();
String baseKey = itemsKey(kind);
jedis.watch(baseKey);
if (updateListener != null) {
updateListener.aboutToUpdate(baseKey, key);
}
String oldItemJson = getRedis(kind, key, jedis);
// In this implementation, we have to parse the existing item in order to determine its version.
int oldVersion = oldItemJson == null ? -1 : kind.deserialize(oldItemJson).getVersion();
if (oldVersion >= newItem.getVersion()) {
logger.debug("Attempted to {} key: {} version: {}" +
" with a version that is the same or older: {} in \"{}\"",
newItem.getSerializedItem() == null ? "delete" : "update",
key, oldVersion, newItem.getVersion(), kind.getName());
return false;
}
Transaction tx = jedis.multi();
tx.hset(baseKey, key, jsonOrPlaceholder(kind, newItem));
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy