Преглед на файлове

Refactor retry in redis service

pull/10/head
Kristijan Mitrovic преди 4 години
родител
ревизия
f8f4576caf
променени са 1 файла, в които са добавени 201 реда и са изтрити 583 реда
  1. +201
    -583
      wizard-server/src/main/java/org/cobbzilla/wizard/cache/redis/RedisService.java

+ 201
- 583
wizard-server/src/main/java/org/cobbzilla/wizard/cache/redis/RedisService.java Целия файл

@@ -2,22 +2,22 @@ package org.cobbzilla.wizard.cache.redis;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.collection.SingletonSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

import javax.annotation.Nullable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static net.sf.cglib.core.CollectionUtils.transform;
import static org.cobbzilla.util.daemon.ZillaRuntime.*;
import static org.cobbzilla.util.daemon.ZillaRuntime.now;
import static org.cobbzilla.util.json.JsonUtil.fromJsonOrDie;
import static org.cobbzilla.util.json.JsonUtil.toJsonOrDie;
import static org.cobbzilla.util.security.CryptoUtil.string_decrypt;
@@ -27,7 +27,7 @@ import static org.cobbzilla.util.system.Sleep.sleep;
@Service @NoArgsConstructor @Slf4j
public class RedisService {

public static final int MAX_RETRIES = 5;
public static final byte MAX_RETRIES = 5;

public static final String NX = "NX";
public static final String XX = "XX";
@@ -40,10 +40,12 @@ public class RedisService {
@Autowired @Getter @Setter private HasRedisConfiguration configuration;

@Getter @Setter private String key;
protected boolean hasKey () { return !empty(getKey()); }
protected boolean hasKey() { return !empty(getKey()); }

private final AtomicReference<Jedis> redis = new AtomicReference<>();
private Jedis newJedis() { return new Jedis(configuration.getRedis().getHost(), configuration.getRedis().getPort()); }
private Jedis newJedis() {
return new Jedis(configuration.getRedis().getHost(), configuration.getRedis().getPort());
}

@Getter @Setter private String prefix = null;

@@ -55,7 +57,7 @@ public class RedisService {
this(configuration.getRedis(), prefix, key);
}

public RedisService(RedisConfiguration configuration, String prefix, String key) {
public RedisService(final RedisConfiguration configuration, String prefix, String key) {
this.configuration = () -> configuration;
this.prefix = prefix;
this.key = key;
@@ -63,7 +65,9 @@ public class RedisService {

private Map<String, RedisService> prefixServiceCache = new ConcurrentHashMap<>();

public RedisService prefixNamespace(String prefix) { return prefixNamespace(prefix, configuration.getRedis().getKey()); }
public RedisService prefixNamespace(String prefix) {
return prefixNamespace(prefix, configuration.getRedis().getKey());
}

public RedisService prefixNamespace(String prefix, String key) {
RedisService r = prefixServiceCache.get(prefix);
@@ -74,10 +78,9 @@ public class RedisService {
prefixServiceCache.put(prefix, r);
}
return r;

}

public void reconnect () {
public void reconnect() {
if (log.isDebugEnabled()) log.debug("marking redis for reconnection...");
synchronized (redis) {
if (redis.get() != null) {
@@ -89,7 +92,7 @@ public class RedisService {
}
}

private Jedis getRedis () {
private Jedis getRedis() {
synchronized (redis) {
if (redis.get() == null) {
if (log.isDebugEnabled()) log.debug("connecting to redis...");
@@ -99,19 +102,21 @@ public class RedisService {
return redis.get();
}

public <V> RedisMap<V> map (String prefix) { return map(prefix, null); }
public <V> RedisMap<V> map (String prefix, Long duration) { return new RedisMap<>(prefix, duration, this); }
public <V> RedisMap<V> map(String prefix) { return map(prefix, null); }
public <V> RedisMap<V> map(String prefix, Long duration) { return new RedisMap<>(prefix, duration, this); }

public boolean exists(String key) { return __exists(key, 0, MAX_RETRIES); }
public boolean exists(@NonNull final String key) {
return retry(() -> getRedis().exists(prefix(key)), "exists");
}

public boolean anyExists(Collection<String> keys) {
public boolean anyExists(@NonNull final Collection<String> keys) {
for (String k : keys) if (exists(k)) return true;
return false;
}

public boolean allExist(Collection<String> keys) {
for (String k : keys) if (!exists(k)) return false;
return true;
public boolean allExist(@NonNull final Collection<String> keys) {
final var prefixedKeysArray = keys.stream().map(k -> prefix(k)).toArray(String[]::new);
return keys.size() == retry(() -> getRedis().exists(prefixedKeysArray), "exists");
}

public <T> T getObject(String key, Class<T> clazz) {
@@ -119,124 +124,197 @@ public class RedisService {
return empty(json) ? null : fromJsonOrDie(json, clazz);
}

public String get(String key) { return decrypt(__get(key, 0, MAX_RETRIES)); }
public String get_withPrefix(String prefixedKey) { return decrypt(__get(prefixedKey, 0, MAX_RETRIES, false)); }
@Nullable public String get(@NonNull final String key) {
return decrypt(retry(() -> getRedis().get(prefix(key)), "get"));
}
@Nullable public String get_withPrefix(@NonNull final String prefixedKey) {
return decrypt(retry(() -> getRedis().get(prefixedKey), "get"));
}
@Nullable public String get_plaintext(@NonNull final String key) {
return retry(() -> getRedis().get(prefix(key)), "get");
}

public String get_plaintext(String key) { return __get(key, 0, MAX_RETRIES); }

public void set(String key, String value, String nxxx, String expx, long time) {
__set(key, value, nxxx, expx, time, 0, MAX_RETRIES);
public void set(@NonNull final String key, @NonNull final String value) {
retry(() -> getRedis().set(prefix(key), encrypt(value)), "set");
}
public <T> void setObject(@NonNull final String key, @NonNull final T thing) { set(key, toJsonOrDie(thing)); }

public void set(String key, String value, String expx, long time) {
__set(key, value, XX, expx, time, 0, MAX_RETRIES);
__set(key, value, NX, expx, time, 0, MAX_RETRIES);
public void set(@NonNull final String key, @NonNull final String value, @NonNull final String nxxx,
@NonNull final String expx, final long time) {
retry(() -> getRedis().set(prefix(key), encrypt(value), buildSetParams(nxxx, expx, time)), "set");
}
public void set(@NonNull final String key, @NonNull final String value, @NonNull final String expx,
final long time) {
set(key, value, XX, expx, time);
set(key, value, NX, expx, time);
}
public void setAll(@NonNull final Collection<String> keys, @NonNull final String value, @NonNull final String expx,
final long time) {
for (String k : keys) set(k, value, expx, time);
}

public void set(String key, String value) { __set(key, value, 0, MAX_RETRIES); }
public void set_plaintext(@NonNull final String key, @NonNull final String value) {
retry(() -> getRedis().set(prefix(key), value), "set_plaintext");
}

public void set_plaintext(String key, String value, String nxxx, String expx, long time) {
__set_plaintext(key, value, nxxx, expx, time, 0, MAX_RETRIES);
public void set_plaintext(@NonNull final String key, @NonNull final String value, @NonNull final String nxxx,
@NonNull final String expx, final long time) {
retry(() -> getRedis().set(prefix(key), value, buildSetParams(nxxx, expx, time)), "set_plaintext");
}

public void set_plaintext(String key, String value, String expx, long time) {
__set_plaintext(key, value, XX, expx, time, 0, MAX_RETRIES);
__set_plaintext(key, value, NX, expx, time, 0, MAX_RETRIES);
public void set_plaintext(@NonNull final String key, @NonNull final String value, @NonNull final String expx,
final long time) {
set_plaintext(key, value, XX, expx, time);
set_plaintext(key, value, NX, expx, time);
}

public void set_plaintext(String key, String value) { __set_plaintext(key, value, 0, MAX_RETRIES); }
public Long touch(@NonNull final String key) { return retry(() -> getRedis().touch(prefix(key)), "touch"); }

public void setAll(Collection<String> keys, String value, String expx, long time) {
for (String k : keys) set(k, value, expx, time);
public Long expire(@NonNull final String key, final int ttlSeconds) {
return retry(() -> getRedis().expire(prefix(key), ttlSeconds), "expire");
}

public <T> void setObject(String key, T thing) { __set(key, toJsonOrDie(thing), 0, MAX_RETRIES); }

public Long touch(String key) { return __touch(key, 0, MAX_RETRIES); }
public Long expire(String key, long ttl) { return __expire(key, (int) ttl, 0, MAX_RETRIES); }
public Long pexpire(String key, long ttl) { return __pexpire(key, (int) ttl, 0, MAX_RETRIES); }
public Long pexpire(@NonNull final String key, final long ttlMillis) {
return retry(() -> getRedis().pexpire(prefix(key), ttlMillis), "pexpire");
}

public List<String> list(String key) { return lrange(key, 0, -1); }
public Long llen(String key) { return __llen(key, 0, MAX_RETRIES); }
public List<String> lrange(String key, int start, int end) { return __lrange(key, start, end, 0, MAX_RETRIES); }
public void lpush(String key, String value) { __lpush(key, value, 0, MAX_RETRIES); }
public String lpop(String data) { return decrypt(__lpop(data, 0, MAX_RETRIES)); }
public void rpush(String key, String value) { __rpush(key, value, 0, MAX_RETRIES); }
public String rpop(String data) { return decrypt(__rpop(data, 0, MAX_RETRIES)); }
public List<String> list(@NonNull final String key) { return lrange(key, 0, -1); }
public List<String> lrange(@NonNull final String key, final int start, final int end) {
final var list = retry(() -> getRedis().lrange(prefix(key), start, end), "lrange");
return hasKey() ? list.stream().map(this::decrypt).collect(Collectors.toList()) : list;
}

public void hset(String key, String field, String value) { __hset(key, field, value, 0, MAX_RETRIES); }
public String hget(String key, String field) { return decrypt(__hget(key, field, 0, MAX_RETRIES)); }
public Map<String, String> hgetall(String key) { return decrypt(__hgetall(key, 0, MAX_RETRIES)); }
public Long llen(@NonNull final String key) {
return retry(() -> getRedis().llen(prefix(key)), "llen");
}
public void lpush(@NonNull final String key, @NonNull final String value) {
retry(() -> getRedis().lpush(prefix(key), encrypt(value)), "lpush");
}
public String lpop(@NonNull final String key) {
return decrypt(retry(() -> getRedis().lpop(prefix(key)), "lpop"));
}
public void rpush(@NonNull final String key, @NonNull final String value) {
retry(() -> getRedis().rpush(prefix(key), encrypt(value)), "rpush");
}
public String rpop(@NonNull final String key) {
return decrypt(retry(() -> getRedis().rpop(prefix(key)), "rpop"));
}

private Map<String, String> decrypt(Map<String, String> map) {
public void hset(@NonNull final String key, @NonNull final String field, @NonNull final String value) {
retry(() -> getRedis().hset(prefix(key), encrypt(field), encrypt(value)), "hget");
}
public String hget(@NonNull final String key, @NonNull final String field) {
if (empty(field)) return die("__hget(" + key + "/): field was empty");
return decrypt(retry(() -> getRedis().hget(prefix(key), encrypt(field)), "hget"));
}
public Map<String, String> hgetall(@NonNull final String key) {
final var map = retry(() -> getRedis().hgetAll(prefix(key)), "hgetall");
if (!hasKey()) return map;
final Map<String, String> decrypted = new HashMap<>();
for (Map.Entry<String, String> entry : map.entrySet()) {

final var decrypted = new HashMap<String, String>(map.size());
for (final var entry : map.entrySet()) {
decrypted.put(decrypt(entry.getKey()), decrypt(entry.getValue()));
}
return decrypted;
}
public Long hdel(@NonNull final String key, @NonNull final String field) {
return retry(() -> getRedis().hdel(prefix(key), encrypt(field)), "hdel");
}
public Set<String> hkeys(@NonNull final String key) {
return retry(() -> getRedis().hkeys(prefix(key)), "hget");
}
public Long hlen(@NonNull final String key) {
return retry(() -> getRedis().hlen(prefix(key)), "hlen");
}

public Long hdel(String key, String field) { return __hdel(key, field, 0, MAX_RETRIES); }
public Set<String> hkeys(String key) { return __hkeys(key, 0, MAX_RETRIES); }
public Long hlen(String key) { return __hlen(key, 0, MAX_RETRIES); }

public Long del(String key) { return __del(key, 0, MAX_RETRIES); }
public Long del_withPrefix(String prefixedKey) { return __del(prefixedKey, 0, MAX_RETRIES, false); }

public Long del_matching(String keyMatch) {
Long count = 0L;
for (String key : keys(keyMatch)) {
public Long del(@NonNull final String key) {
return retry(() -> getRedis().del(prefix(key)), "del");
}
public Long del_withPrefix(@NonNull final String prefixedKey) {
return retry(() -> getRedis().del(prefixedKey), "del");
}
public Long del_matching(@NonNull final String keyMatch) {
var count = 0L;
for (final var key : keys(keyMatch)) {
count += del_withPrefix(key);
}
return count;
}

public Long sadd(String key, String value) { return sadd(key, new String[]{value}); }
public Long sadd(String key, String[] values) { return __sadd(key, values, 0, MAX_RETRIES); }

public Long sadd_plaintext(String key, String value) { return sadd_plaintext(key, new String[]{value}); }
public Long sadd_plaintext(String key, String[] values) { return __sadd(key, values, 0, MAX_RETRIES, false); }

public Long srem(String key, String value) { return srem(key, new String[]{value}); }
public Long srem(String key, String[] values) { return __srem(key, values, 0, MAX_RETRIES); }

public Set<String> smembers(String key) { return __smembers(key, 0, MAX_RETRIES); }
public boolean sismember(String key, String value) { return __sismember(key, value, 0, MAX_RETRIES); }

public List<String> srandmembers(String key, int count) { return __srandmember(key, count, 0, MAX_RETRIES); }
public String srandmember(String key) {
final List<String> rand = srandmembers(key, 1);
public Long sadd(@NonNull final String key, final String value) { return sadd(key, new String[]{value}); }
public Long sadd(@NonNull final String key, final String[] values) {
return retry(() -> getRedis().sadd(prefix(key), encrypt(values)), "sadd");
}
public Long sadd_plaintext(@NonNull final String key, final String value) {
return sadd_plaintext(key, new String[]{value});
}
public Long sadd_plaintext(@NonNull final String key, final String[] values) {
return retry(() -> getRedis().sadd(prefix(key), values), "sadd");
}
public Long srem(@NonNull final String key, final String value) { return srem(key, new String[]{value}); }
public Long srem(@NonNull final String key, final String[] values) {
return retry(() -> getRedis().srem(prefix(key), encrypt(values)), "srem");
}
public Set<String> smembers(@NonNull final String key) {
return retry(() -> decrypt(getRedis().smembers(prefix(key))), "smembers");
}
public boolean sismember(@NonNull final String key, @NonNull final String value) {
return retry(() -> getRedis().sismember(prefix(key), encrypt(value)), "sismember");
}
public List<String> srandmembers(@NonNull final String key, final int count) {
return retry(() -> decrypt(getRedis().srandmember(prefix(key), count)), "srandmember");
}
public String srandmember(@NonNull final String key) {
final var rand = srandmembers(key, 1);
return empty(rand) ? null : rand.get(0);
}

public String spop(String key) {
final Set<String> popped = spop(key, 1);
return empty(popped) ? null : popped.iterator().next();
@Nullable public Set<String> spop(@NonNull final String key, final long count) {
return retry(() -> decrypt(getRedis().spop(prefix(key), count)), "spop");
}
@Nullable public String spop(@NonNull final String key) {
final var member = spop(key, 1);
return empty(member) ? null : member.iterator().next();
}
public long scard(@NonNull final String key) {
return retry(() -> getRedis().scard(prefix(key)), "scard");
}
public Set<String> sunion(@NonNull final Collection<String> keys) {
return decrypt(sunion_plaintext(keys));
}
public Set<String> sunion_plaintext(@NonNull final Collection<String> keys) {
String[] prefixedKeys = keys.stream().map(this::prefix).toArray(String[]::new);
return retry(() -> getRedis().sunion(prefixedKeys), "sunion");
}
public Long sunionstore((@NonNull final String destKey, (@NonNull final Collection<String> keys) {
String[] prefixedKeys = keys.stream().map(this::prefix).toArray(String[]::new);
return retry(() -> getRedis().sunionstore(prefix(destKey), prefixedKeys), "sunionstore");
}
public Set<String> spop(String key, long count) { return __spop(key, count, 0, MAX_RETRIES); }

public long scard(String key) { return __scard(key, 0, MAX_RETRIES); }

public Set<String> sunion(Collection<String> keys) { return __sunion(keys, 0, MAX_RETRIES); }
public Set<String> sunion_plaintext(Collection<String> keys) { return __sunion(keys, 0, MAX_RETRIES, false); }

public Long sunionstore(String destKey, Collection<String> keys) { return __sunionstore(destKey, keys, 0, MAX_RETRIES); }

public Long incr(String key) { return __incrBy(key, 1, 0, MAX_RETRIES); }
public Long counterValue(String key) {
final String value = get_plaintext(key);
@Nullable public Long counterValue(@NonNull final String key) {
final var value = get_plaintext(key);
return value == null ? null : Long.parseLong(value);
}
public Long incr(@NonNull final String key) {
return retry(() -> getRedis().incrBy(prefix(key), 1), "incrBy");
}
public Long incrBy(@NonNull final String key, final long value) {
return retry(() -> getRedis().incrBy(prefix(key), value), "incrBy");
}
public Long decr(@NonNull final String key) {
return retry(() -> getRedis().decrBy(prefix(key), 1), "decrBy");
}
public Long decrBy(@NonNull final String key, final long value) {
return retry(() -> getRedis().decrBy(prefix(key), value), "decrBy");
}

public Long incrBy(String key, long value) { return __incrBy(key, value, 0, MAX_RETRIES); }
public Long decr(String key) { return __decrBy(key, 1, 0, MAX_RETRIES); }

public Long decrBy(String key, long value) { return __decrBy(key, value, 0, MAX_RETRIES); }

public Collection<String> keys(String key) { return __keys(key, 0, MAX_RETRIES); }
public Collection<String> keys(@NonNull final String key) {
return retry(() -> getRedis().keys(prefix(key)), "keys");
}

public String rename(String key, String newKey) { return __rename(key, newKey, 0, MAX_RETRIES); }
public String rename(@NonNull final String key, @NonNull final String newKey) {
retry(() -> getRedis().rename(prefix(key), newKey), "rename");
}

public static final String LOCK_SUFFIX = "._lock";

@@ -280,47 +358,27 @@ public class RedisService {
}
}

public String loadScript(String script) { return __loadScript(script, 0, MAX_RETRIES); }

private String __loadScript(String script, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().scriptLoad(script);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__loadScript");
return __loadScript(script, attempt+1, maxRetries);
}
public String loadScript(final String script) {
return retry(() -> getRedis().scriptLoad(script), "loadScript");
}


public Object eval(String scriptsha, List<String> keys, List<String> args) {
return __eval(scriptsha, prefix(keys), args, 0, MAX_RETRIES);
public Object eval(final String scriptSHA, final List<String> keys, final List<String> args) {
return retry(() -> getRedis().evalsha(scriptSHA, prefix(keys), args), "eval");
}
public String prefix(String key) { return empty(prefix) ? key : prefix + "." + key; }

private Object __eval(String scriptsha, List<String> keys, List<String> args, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().evalsha(scriptsha, keys, args);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__eval");
return __eval(scriptsha, keys, args, attempt+1, maxRetries);
}
public List<String> prefix(Collection<String> keys) {
return keys.parallelStream().map(this::prefix).collect(Collectors.toList());
}

public String prefix (String key) { return empty(prefix) ? key : prefix + "." + key; }
public List<String> prefix(Collection<String> keys) { return transform(keys, o -> prefix(o.toString())); }

// override these for full control

protected String encrypt(String data) {
if (!hasKey()) return data;
return string_encrypt(data, getKey());
}

protected String[] encrypt(String[] data) {
protected String[] encrypt(final String[] data) {
if (!hasKey() || empty(data)) return data;
final String[] encrypted = new String[data.length];
for (int i=0; i<data.length; i++) {
@@ -334,7 +392,6 @@ public class RedisService {
if (data == null) return null;
return string_decrypt(data, getKey());
}

protected <T extends Collection<String>> T decrypt(T data) {
if (!hasKey() || empty(data)) return data;
final T decrypted = (T) new ArrayList<String>();
@@ -343,6 +400,7 @@ public class RedisService {
}
return decrypted;
}

protected String[] decrypt(String[] data) {
if (!hasKey() || empty(data)) return data;
final String[] decrypted = new String[data.length];
@@ -352,40 +410,24 @@ public class RedisService {
return decrypted;
}

private void resetForRetry(int attempt, String reason) {
reconnect();
sleep(attempt * 10, reason);
}

private String __get(String key, int attempt, int maxRetries) {
return __get(key, attempt, maxRetries, true);
}

private String __get(String key, int attempt, int maxRetries, boolean applyPrefix) {
try {
synchronized (redis) {
return getRedis().get(applyPrefix ? prefix(key) : key);
@Nullable private <T> T retry(@NonNull final Supplier<T> function, @NonNull final String logSuffix) {
for (var attempt = 1; attempt <= MAX_RETRIES; attempt++) {
try {
synchronized (redis) {
return function.get();
}
} catch (RuntimeException e) {
if (attempt >= MAX_RETRIES) throw e; // here's the final exit from the loop (no need to reconnect)
reconnect();
sleep(attempt * 10, "retrying RedisService " + logSuffix);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__get");
return __get(key, attempt+1, maxRetries);
}
}

private boolean __exists(String key, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().exists(prefix(key));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__exists");
return __exists(key, attempt+1, maxRetries);
}
// Should not happen, but just in case:
throw new RuntimeException("retry: Something went wrong while working with redis");
}

private SetParams getSetParams(String nxxx, String expx, long time) {
private SetParams buildSetParams(String nxxx, String expx, long time) {
SetParams setParams = new SetParams();
switch (nxxx) {
case NX: setParams.nx(); break;
@@ -398,430 +440,6 @@ public class RedisService {
return setParams;
}

private String __set(String key, String value, String nxxx, String expx, long time, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().set(prefix(key), encrypt(value), getSetParams(nxxx, expx, time));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__set");
return __set(key, value, nxxx, expx, time, attempt + 1, maxRetries);
}
}

private String __set(String key, String value, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().set(prefix(key), encrypt(value));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__set");
return __set(key, value, attempt+1, maxRetries);
}
}

private String __set_plaintext(String key, String value, String nxxx, String expx, long time, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().set(prefix(key), value, getSetParams(nxxx, expx, time));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__set_plaintext");
return __set_plaintext(key, value, nxxx, expx, time, attempt + 1, maxRetries);
}
}

private String __set_plaintext(String key, String value, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().set(prefix(key), value);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__set_plaintext");
return __set_plaintext(key, value, attempt+1, maxRetries);
}
}

private Long __touch(String key, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().touch(prefix(key));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__touch");
return __touch(key, attempt+1, maxRetries);
}
}

private Long __expire(String key, int ttl, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().expire(prefix(key), ttl);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__expire");
return __expire(key, ttl, attempt+1, maxRetries);
}
}

private Long __pexpire(String key, long ttl, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().pexpire(prefix(key), ttl);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__pexpire");
return __pexpire(key, ttl, attempt+1, maxRetries);
}
}

private Long __lpush(String key, String value, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().lpush(prefix(key), encrypt(value));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__lpush");
return __lpush(key, value, attempt + 1, maxRetries);
}
}

private String __lpop(String key, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().lpop(prefix(key));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__lpop");
return __lpop(key, attempt+1, maxRetries);
}
}

private Long __rpush(String key, String value, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().rpush(prefix(key), encrypt(value));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__rpush");
return __rpush(key, value, attempt + 1, maxRetries);
}
}

private String __rpop(String data, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().rpop(data);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__rpop");
return __rpop(data, attempt+1, maxRetries);
}
}

private String __hget(String key, String field, int attempt, int maxRetries) {
if (empty(field)) return die("__hget("+key+"/): field was empty");
try {
synchronized (redis) {
return getRedis().hget(prefix(key), encrypt(field));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__hget");
return __hget(key, field, attempt + 1, maxRetries);
}
}

private Map<String, String> __hgetall(String key, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().hgetAll(prefix(key));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__hgetall");
return __hgetall(key, attempt + 1, maxRetries);
}
}

private Long __hset(String key, String field, String value, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().hset(prefix(key), encrypt(field), encrypt(value));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__hget");
return __hset(key, field, value, attempt + 1, maxRetries);
}
}

private Long __hdel(String key, String field, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().hdel(prefix(key), encrypt(field));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__hdel");
return __hdel(key, field, attempt + 1, maxRetries);
}
}

private Set<String> __hkeys(String key, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().hkeys(prefix(key));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__hget");
return __hkeys(key, attempt + 1, maxRetries);
}
}

private Long __hlen(String key, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().hlen(prefix(key));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__hlen");
return __hlen(key, attempt + 1, maxRetries);
}
}

private Long __del(String key, int attempt, int maxRetries) {
return __del(key, attempt, maxRetries, true);
}

private Long __del(String key, int attempt, int maxRetries, boolean applyPrefix) {
try {
synchronized (redis) {
return getRedis().del(applyPrefix ? prefix(key) : key);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__del");
return __del(key, attempt+1, maxRetries, applyPrefix);
}
}

private Long __sadd(String key, String[] members, int attempt, int maxRetries) {
return __sadd(key, members, attempt, maxRetries, true);
}

private Long __sadd(String key, String[] members, int attempt, int maxRetries, boolean crypt) {
try {
synchronized (redis) {
return getRedis().sadd(prefix(key), crypt ? encrypt(members) : members);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__sadd");
return __sadd(key, members, attempt+1, maxRetries);
}
}

private Long __srem(String key, String[] members, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().srem(prefix(key), encrypt(members));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__srem");
return __srem(key, members, attempt+1, maxRetries);
}
}

private Set<String> __smembers(String key, int attempt, int maxRetries) {
try {
synchronized (redis) {
return decrypt(getRedis().smembers(prefix(key)));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__smembers");
return __smembers(key, attempt+1, maxRetries);
}
}

private boolean __sismember(String key, String value, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().sismember(prefix(key), encrypt(value));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__sismember");
return __sismember(key, value, attempt+1, maxRetries);
}
}

private List<String> __srandmember(String key, int count, int attempt, int maxRetries) {
try {
synchronized (redis) {
return decrypt(getRedis().srandmember(prefix(key), count));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__srandmember");
return __srandmember(key, count, attempt+1, maxRetries);
}
}

private Set<String> __spop(String key, long count, int attempt, int maxRetries) {
try {
synchronized (redis) {
return decrypt(count == 1 ? new SingletonSet<>(getRedis().spop(prefix(key))) : getRedis().spop(prefix(key), count));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__spop");
return __spop(key, count, attempt+1, maxRetries);
}
}

private Long __scard(String key, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().scard(prefix(key));
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__scard");
return __scard(key, attempt+1, maxRetries);
}
}

private Set<String> __sunion(Collection<String> keys, int attempt, int maxRetries) {
return __sunion(keys, attempt, maxRetries, true);
}
private Set<String> __sunion(Collection<String> keys, int attempt, int maxRetries, boolean crypt) {
try {
String[] prefixedKeys = keys.stream().map(this::prefix).toArray(String[]::new);
synchronized (redis) {
final Set<String> values = getRedis().sunion(prefixedKeys);
return crypt ? values.stream().map(this::decrypt).collect(Collectors.toSet()) : values;
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__sunion");
return __sunion(keys, attempt+1, maxRetries);
}
}

private Long __sunionstore(String destKey, Collection<String> keys, int attempt, int maxRetries) {
try {
String[] prefixedKeys = keys.stream().map(this::prefix).toArray(String[]::new);
synchronized (redis) {
return getRedis().sunionstore(prefix(destKey), prefixedKeys);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__sunionstore");
return __sunionstore(destKey, keys, attempt+1, maxRetries);
}
}

private Long __incrBy(String key, long value, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().incrBy(prefix(key), value);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__incrBy");
return __incrBy(key, value, attempt + 1, maxRetries);
}
}

private Long __decrBy(String key, long value, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().decrBy(prefix(key), value);
}
} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__decrBy");
return __decrBy(key, value, attempt+1, maxRetries);
}
}

private Long __llen(String key, int attempt, int maxRetries) {
try {
synchronized (redis) {
return getRedis().llen(prefix(key));
}

} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__llen");
return __llen(key, attempt + 1, maxRetries);
}
}

private List<String> __lrange(String key, int start, int end, int attempt, int maxRetries) {
try {
final List<String> range;
synchronized (redis) {
range = getRedis().lrange(prefix(key), start, end);
}
final List<String> list = new ArrayList<>(range.size());
for (String item : range) list.add(decrypt(item));

return list;

} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__lrange");
return __lrange(key, start, end, attempt + 1, maxRetries);
}
}

private Collection<String> __keys(String key, int attempt, int maxRetries) {
try {
final Set<String> keys;
synchronized (redis) {
keys = getRedis().keys(prefix(key));
}
return keys;

} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__keys");
return __keys(key, attempt + 1, maxRetries);
}
}

private String __rename(String key, String newKey, int attempt, int maxRetries) {
try {
final String rval;
synchronized (redis) {
rval = getRedis().rename(prefix(key), newKey);
}
return rval;

} catch (RuntimeException e) {
if (attempt > maxRetries) throw e;
resetForRetry(attempt, "retrying RedisService.__rename");
return __rename(key, newKey, attempt + 1, maxRetries);
}
}

public void flush() { del_matching(ALL_KEYS); }

}

Зареждане…
Отказ
Запис