diff --git a/wizard-server/src/main/java/org/cobbzilla/wizard/cache/redis/RedisService.java b/wizard-server/src/main/java/org/cobbzilla/wizard/cache/redis/RedisService.java index 56eacc8..1c16a03 100644 --- a/wizard-server/src/main/java/org/cobbzilla/wizard/cache/redis/RedisService.java +++ b/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 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 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 RedisMap map (String prefix) { return map(prefix, null); } - public RedisMap map (String prefix, Long duration) { return new RedisMap<>(prefix, duration, this); } + public RedisMap map(String prefix) { return map(prefix, null); } + public RedisMap 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 keys) { + public boolean anyExists(@NonNull final Collection keys) { for (String k : keys) if (exists(k)) return true; return false; } - public boolean allExist(Collection keys) { - for (String k : keys) if (!exists(k)) return false; - return true; + public boolean allExist(@NonNull final Collection keys) { + final var prefixedKeysArray = keys.stream().map(k -> prefix(k)).toArray(String[]::new); + return keys.size() == retry(() -> getRedis().exists(prefixedKeysArray), "exists"); } public T getObject(String key, Class 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 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 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 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 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 list(String key) { return lrange(key, 0, -1); } - public Long llen(String key) { return __llen(key, 0, MAX_RETRIES); } - public List 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 list(@NonNull final String key) { return lrange(key, 0, -1); } + public List 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 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 decrypt(Map 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 hgetall(@NonNull final String key) { + final var map = retry(() -> getRedis().hgetAll(prefix(key)), "hgetall"); if (!hasKey()) return map; - final Map decrypted = new HashMap<>(); - for (Map.Entry entry : map.entrySet()) { + + final var decrypted = new HashMap(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 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 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 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 srandmembers(String key, int count) { return __srandmember(key, count, 0, MAX_RETRIES); } - public String srandmember(String key) { - final List 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 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 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 popped = spop(key, 1); - return empty(popped) ? null : popped.iterator().next(); + @Nullable public Set 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 sunion(@NonNull final Collection keys) { + return decrypt(sunion_plaintext(keys)); + } + public Set sunion_plaintext(@NonNull final Collection 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 keys) { + String[] prefixedKeys = keys.stream().map(this::prefix).toArray(String[]::new); + return retry(() -> getRedis().sunionstore(prefix(destKey), prefixedKeys), "sunionstore"); } - public Set 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 sunion(Collection keys) { return __sunion(keys, 0, MAX_RETRIES); } - public Set sunion_plaintext(Collection keys) { return __sunion(keys, 0, MAX_RETRIES, false); } - - public Long sunionstore(String destKey, Collection 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 keys(String key) { return __keys(key, 0, MAX_RETRIES); } + public Collection 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 keys, List args) { - return __eval(scriptsha, prefix(keys), args, 0, MAX_RETRIES); + public Object eval(final String scriptSHA, final List keys, final List 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 keys, List 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 prefix(Collection keys) { + return keys.parallelStream().map(this::prefix).collect(Collectors.toList()); } - - public String prefix (String key) { return empty(prefix) ? key : prefix + "." + key; } - public List prefix(Collection 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> T decrypt(T data) { if (!hasKey() || empty(data)) return data; final T decrypted = (T) new ArrayList(); @@ -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 retry(@NonNull final Supplier 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 __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 __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 __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 __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 __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 __sunion(Collection keys, int attempt, int maxRetries) { - return __sunion(keys, attempt, maxRetries, true); - } - private Set __sunion(Collection keys, int attempt, int maxRetries, boolean crypt) { - try { - String[] prefixedKeys = keys.stream().map(this::prefix).toArray(String[]::new); - synchronized (redis) { - final Set 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 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 __lrange(String key, int start, int end, int attempt, int maxRetries) { - try { - final List range; - synchronized (redis) { - range = getRedis().lrange(prefix(key), start, end); - } - final List 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 __keys(String key, int attempt, int maxRetries) { - try { - final Set 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); } }