CacheSource增加zincrby方法
This commit is contained in:
@@ -9,7 +9,7 @@ import java.io.Serializable;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.*;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
@@ -118,7 +118,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
scheduler.scheduleWithFixedDelay(() -> {
|
scheduler.scheduleWithFixedDelay(() -> {
|
||||||
try {
|
try {
|
||||||
keys.clear();
|
keys.clear();
|
||||||
int now = (int) (System.currentTimeMillis() / 1000);
|
long now = System.currentTimeMillis();
|
||||||
container.forEach((k, x) -> {
|
container.forEach((k, x) -> {
|
||||||
if (x.expireSeconds > 0 && (now > (x.lastAccessed + x.expireSeconds))) {
|
if (x.expireSeconds > 0 && (now > (x.lastAccessed + x.expireSeconds))) {
|
||||||
keys.add(x.key);
|
keys.add(x.key);
|
||||||
@@ -227,7 +227,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
}
|
}
|
||||||
Serializable val = (Serializable) entry.mapValue.computeIfAbsent(field, f -> new AtomicLong());
|
Serializable val = (Serializable) entry.mapValue.computeIfAbsent(field, f -> new AtomicLong());
|
||||||
if (!(val instanceof AtomicLong)) {
|
if (!(val instanceof AtomicLong)) {
|
||||||
entry.mapLock.lock();
|
entry.lock.lock();
|
||||||
try {
|
try {
|
||||||
if (!(val instanceof AtomicLong)) {
|
if (!(val instanceof AtomicLong)) {
|
||||||
if (val == null) {
|
if (val == null) {
|
||||||
@@ -238,7 +238,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
entry.mapValue.put(field, val);
|
entry.mapValue.put(field, val);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
entry.mapLock.unlock();
|
entry.lock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ((AtomicLong) entry.mapValue.get(field)).addAndGet(num);
|
return ((AtomicLong) entry.mapValue.get(field)).addAndGet(num);
|
||||||
@@ -265,7 +265,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
}
|
}
|
||||||
Serializable val = (Serializable) entry.mapValue.computeIfAbsent(field, f -> new AtomicLong());
|
Serializable val = (Serializable) entry.mapValue.computeIfAbsent(field, f -> new AtomicLong());
|
||||||
if (!(val instanceof AtomicLong)) {
|
if (!(val instanceof AtomicLong)) {
|
||||||
entry.mapLock.lock();
|
entry.lock.lock();
|
||||||
try {
|
try {
|
||||||
if (!(val instanceof AtomicLong)) {
|
if (!(val instanceof AtomicLong)) {
|
||||||
if (val == null) {
|
if (val == null) {
|
||||||
@@ -276,7 +276,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
entry.mapValue.put(field, val);
|
entry.mapValue.put(field, val);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
entry.mapLock.unlock();
|
entry.lock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Double.longBitsToDouble(((AtomicLong) entry.mapValue.get(field)).addAndGet(Double.doubleToLongBits(num)));
|
return Double.longBitsToDouble(((AtomicLong) entry.mapValue.get(field)).addAndGet(Double.doubleToLongBits(num)));
|
||||||
@@ -468,7 +468,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
if (entry == null || entry.isExpired()) {
|
if (entry == null || entry.isExpired()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
entry.lastAccessed = (int) (System.currentTimeMillis() / 1000);
|
entry.lastAccessed = System.currentTimeMillis();
|
||||||
entry.expireSeconds = expireSeconds;
|
entry.expireSeconds = expireSeconds;
|
||||||
if (entry.isListCacheType()) {
|
if (entry.isListCacheType()) {
|
||||||
return (T) (entry.listValue == null ? null : new ArrayList(entry.listValue));
|
return (T) (entry.listValue == null ? null : new ArrayList(entry.listValue));
|
||||||
@@ -491,7 +491,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
} else {
|
} else {
|
||||||
entry.expireSeconds = 0;
|
entry.expireSeconds = 0;
|
||||||
entry.objectValue = value;
|
entry.objectValue = value;
|
||||||
entry.lastAccessed = (int) (System.currentTimeMillis() / 1000);
|
entry.lastAccessed = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,7 +506,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
entry.expireSeconds = 0;
|
entry.expireSeconds = 0;
|
||||||
entry.lastAccessed = (int) (System.currentTimeMillis() / 1000);
|
entry.lastAccessed = System.currentTimeMillis();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -523,7 +523,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
} else {
|
} else {
|
||||||
entry.expireSeconds = 0;
|
entry.expireSeconds = 0;
|
||||||
entry.mapValue.put(field, value);
|
entry.mapValue.put(field, value);
|
||||||
entry.lastAccessed = (int) (System.currentTimeMillis() / 1000);
|
entry.lastAccessed = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,7 +539,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
entry.expireSeconds = 0;
|
entry.expireSeconds = 0;
|
||||||
entry.lastAccessed = (int) (System.currentTimeMillis() / 1000);
|
entry.lastAccessed = System.currentTimeMillis();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -648,14 +648,14 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CacheEntry entry = container.get(key);
|
CacheEntry entry = container.get(key);
|
||||||
if (entry == null) {
|
if (entry == null || entry.isExpired()) {
|
||||||
entry = new CacheEntry(cacheType, expireSeconds, key, value, null, null, null);
|
entry = new CacheEntry(cacheType, expireSeconds, key, value, null, null, null);
|
||||||
container.putIfAbsent(key, entry);
|
container.putIfAbsent(key, entry);
|
||||||
} else {
|
} else {
|
||||||
if (expireSeconds > 0) {
|
if (expireSeconds > 0) {
|
||||||
entry.expireSeconds = expireSeconds;
|
entry.expireSeconds = expireSeconds;
|
||||||
}
|
}
|
||||||
entry.lastAccessed = (int) (System.currentTimeMillis() / 1000);
|
entry.lastAccessed = System.currentTimeMillis();
|
||||||
entry.objectValue = value;
|
entry.objectValue = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -665,15 +665,13 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CacheEntry entry = container.get(key);
|
CacheEntry entry = container.get(key);
|
||||||
if (entry == null) {
|
if (entry == null || entry.isExpired()) {
|
||||||
entry = new CacheEntry(cacheType, expireSeconds, key, value, null, null, null);
|
entry = new CacheEntry(cacheType, expireSeconds, key, value, null, null, null);
|
||||||
container.putIfAbsent(key, entry);
|
container.put(key, entry);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (expireSeconds > 0) {
|
entry.expireSeconds = expireSeconds > 0 ? expireSeconds : 0;
|
||||||
entry.expireSeconds = expireSeconds;
|
entry.lastAccessed = System.currentTimeMillis();
|
||||||
}
|
|
||||||
entry.lastAccessed = (int) (System.currentTimeMillis() / 1000);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1297,6 +1295,52 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
}, getExecutor());
|
}, getExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends Number> CompletableFuture<T> zincrbyAsync(String key, CacheScoredValue value) {
|
||||||
|
return supplyAsync(() -> {
|
||||||
|
CacheEntry entry = container.get(key);
|
||||||
|
if (entry == null || entry.isExpired() || entry.csetValue == null) {
|
||||||
|
containerLock.lock();
|
||||||
|
try {
|
||||||
|
entry = container.get(key);
|
||||||
|
if (entry == null || entry.isExpired()) {
|
||||||
|
appendSetItem(CacheEntryType.SET_SORTED, key, List.of(new CacheScoredValue.NumberScoredValue(value.getScore().doubleValue(), value.getValue())));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
containerLock.unlock();
|
||||||
|
}
|
||||||
|
return (T) value.getScore();
|
||||||
|
}
|
||||||
|
entry.lock.lock();
|
||||||
|
try {
|
||||||
|
Set<CacheScoredValue.NumberScoredValue> sets = entry.csetValue;
|
||||||
|
CacheScoredValue.NumberScoredValue old = sets.stream().filter(v -> Objects.equals(v.getValue(), value.getValue())).findAny().orElse(null);
|
||||||
|
if (old == null) {
|
||||||
|
sets.add(new CacheScoredValue.NumberScoredValue(value.getScore().doubleValue(), value.getValue()));
|
||||||
|
return (T) value.getScore();
|
||||||
|
} else {
|
||||||
|
Number ic = value.getScore();
|
||||||
|
if (ic instanceof Integer) {
|
||||||
|
old.setScore((double) (old.getScore().intValue() + ic.intValue()));
|
||||||
|
} else if (ic instanceof Long) {
|
||||||
|
old.setScore((double) (old.getScore().longValue() + ic.longValue()));
|
||||||
|
} else if (ic instanceof Float) {
|
||||||
|
old.setScore((double) (old.getScore().floatValue() + ic.floatValue()));
|
||||||
|
} else if (ic instanceof Double) {
|
||||||
|
old.setScore(old.getScore().doubleValue() + ic.doubleValue());
|
||||||
|
} else if (ic instanceof AtomicInteger) {
|
||||||
|
((AtomicInteger) old.getScore()).addAndGet(((AtomicInteger) ic).get());
|
||||||
|
} else if (ic instanceof AtomicLong) {
|
||||||
|
((AtomicLong) old.getScore()).addAndGet(((AtomicLong) ic).get());
|
||||||
|
}
|
||||||
|
return (T) old.getScore();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
entry.lock.unlock();
|
||||||
|
}
|
||||||
|
}, getExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Long> zcardAsync(String key) {
|
public CompletableFuture<Long> zcardAsync(String key) {
|
||||||
return supplyAsync(() -> {
|
return supplyAsync(() -> {
|
||||||
@@ -1369,6 +1413,9 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private <T extends Number> T formatScore(Class<T> scoreType, Number score) {
|
private <T extends Number> T formatScore(Class<T> scoreType, Number score) {
|
||||||
|
if (score == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (scoreType == int.class || scoreType == Integer.class) {
|
if (scoreType == int.class || scoreType == Integer.class) {
|
||||||
return (T) (Number) score.intValue();
|
return (T) (Number) score.intValue();
|
||||||
} else if (scoreType == long.class || scoreType == Long.class) {
|
} else if (scoreType == long.class || scoreType == Long.class) {
|
||||||
@@ -1393,7 +1440,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Set<CacheScoredValue> sets = entry.csetValue;
|
Set<CacheScoredValue> sets = entry.csetValue;
|
||||||
return (T) sets.stream().filter(v -> Objects.equals(member, v.getValue())).findAny().map(v -> v.getScore()).orElse(null);
|
return formatScore(scoreType, sets.stream().filter(v -> Objects.equals(member, v.getValue())).findAny().map(v -> v.getScore()).orElse(null));
|
||||||
}, getExecutor());
|
}, getExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1498,13 +1545,13 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
//<=0表示永久保存
|
//<=0表示永久保存
|
||||||
int expireSeconds;
|
int expireSeconds;
|
||||||
|
|
||||||
volatile int lastAccessed; //最后刷新时间
|
volatile long lastAccessed; //最后刷新时间
|
||||||
|
|
||||||
T objectValue;
|
T objectValue;
|
||||||
|
|
||||||
ConcurrentHashMap<String, Serializable> mapValue;
|
ConcurrentHashMap<String, Serializable> mapValue;
|
||||||
|
|
||||||
final ReentrantLock mapLock = new ReentrantLock();
|
final ReentrantLock lock = new ReentrantLock();
|
||||||
|
|
||||||
Set<T> csetValue;
|
Set<T> csetValue;
|
||||||
|
|
||||||
@@ -1515,11 +1562,11 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CacheEntry(CacheEntryType cacheType, int expireSeconds, String key, T objectValue, Set<T> csetValue, ConcurrentLinkedDeque<T> listValue, ConcurrentHashMap<String, Serializable> mapValue) {
|
public CacheEntry(CacheEntryType cacheType, int expireSeconds, String key, T objectValue, Set<T> csetValue, ConcurrentLinkedDeque<T> listValue, ConcurrentHashMap<String, Serializable> mapValue) {
|
||||||
this(cacheType, expireSeconds, (int) (System.currentTimeMillis() / 1000), key, objectValue, csetValue, listValue, mapValue);
|
this(cacheType, expireSeconds, System.currentTimeMillis(), key, objectValue, csetValue, listValue, mapValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConstructorParameters({"cacheType", "expireSeconds", "lastAccessed", "key", "objectValue", "csetValue", "listValue", "mapValue"})
|
@ConstructorParameters({"cacheType", "expireSeconds", "lastAccessed", "key", "objectValue", "csetValue", "listValue", "mapValue"})
|
||||||
public CacheEntry(CacheEntryType cacheType, int expireSeconds, int lastAccessed, String key, T objectValue, Set<T> csetValue, ConcurrentLinkedDeque<T> listValue, ConcurrentHashMap<String, Serializable> mapValue) {
|
public CacheEntry(CacheEntryType cacheType, int expireSeconds, long lastAccessed, String key, T objectValue, Set<T> csetValue, ConcurrentLinkedDeque<T> listValue, ConcurrentHashMap<String, Serializable> mapValue) {
|
||||||
this.cacheType = cacheType;
|
this.cacheType = cacheType;
|
||||||
this.expireSeconds = expireSeconds;
|
this.expireSeconds = expireSeconds;
|
||||||
this.lastAccessed = lastAccessed;
|
this.lastAccessed = lastAccessed;
|
||||||
@@ -1552,7 +1599,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
|
|
||||||
@ConvertColumn(ignore = true)
|
@ConvertColumn(ignore = true)
|
||||||
public boolean isExpired() {
|
public boolean isExpired() {
|
||||||
return (expireSeconds > 0 && lastAccessed + expireSeconds < (System.currentTimeMillis() / 1000));
|
return expireSeconds > 0 && (lastAccessed + expireSeconds * 1000) < System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CacheEntryType getCacheType() {
|
public CacheEntryType getCacheType() {
|
||||||
@@ -1563,7 +1610,7 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
return expireSeconds;
|
return expireSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLastAccessed() {
|
public long getLastAccessed() {
|
||||||
return lastAccessed;
|
return lastAccessed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public interface CacheScoredValue<S extends Number> extends Serializable, Compar
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setScore(Long score) {
|
public void setScore(Number score) {
|
||||||
this.score = score;
|
this.score = score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -724,6 +724,22 @@ public interface CacheSource extends Resourcable {
|
|||||||
zadd(key, CacheScoredValue.create(score, member));
|
zadd(key, CacheScoredValue.create(score, member));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default <T extends Number> T zincrby(String key, CacheScoredValue value) {
|
||||||
|
return (T) zincrbyAsync(key, value).join();
|
||||||
|
}
|
||||||
|
|
||||||
|
default int zincrby(String key, int score, String member) {
|
||||||
|
return zincrby(key, CacheScoredValue.create(score, member));
|
||||||
|
}
|
||||||
|
|
||||||
|
default long zincrby(String key, long score, String member) {
|
||||||
|
return zincrby(key, CacheScoredValue.create(score, member));
|
||||||
|
}
|
||||||
|
|
||||||
|
default double zincrby(String key, double score, String member) {
|
||||||
|
return zincrby(key, CacheScoredValue.create(score, member));
|
||||||
|
}
|
||||||
|
|
||||||
default long zrem(String key, String... members) {
|
default long zrem(String key, String... members) {
|
||||||
return zremAsync(key, members).join();
|
return zremAsync(key, members).join();
|
||||||
}
|
}
|
||||||
@@ -1307,6 +1323,20 @@ public interface CacheSource extends Resourcable {
|
|||||||
return zaddAsync(key, CacheScoredValue.create(score, member));
|
return zaddAsync(key, CacheScoredValue.create(score, member));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T extends Number> CompletableFuture<T> zincrbyAsync(String key, CacheScoredValue value);
|
||||||
|
|
||||||
|
default CompletableFuture<Integer> zincrbyAsync(String key, int score, String member) {
|
||||||
|
return zincrbyAsync(key, CacheScoredValue.create(score, member));
|
||||||
|
}
|
||||||
|
|
||||||
|
default CompletableFuture<Long> zincrbyAsync(String key, long score, String member) {
|
||||||
|
return zincrbyAsync(key, CacheScoredValue.create(score, member));
|
||||||
|
}
|
||||||
|
|
||||||
|
default CompletableFuture<Double> zincrbyAsync(String key, double score, String member) {
|
||||||
|
return zincrbyAsync(key, CacheScoredValue.create(score, member));
|
||||||
|
}
|
||||||
|
|
||||||
public CompletableFuture<Long> zremAsync(String key, String... members);
|
public CompletableFuture<Long> zremAsync(String key, String... members);
|
||||||
|
|
||||||
public <T extends Number> CompletableFuture<List<T>> zmscoreAsync(String key, Class<T> scoreType, String... members);
|
public <T extends Number> CompletableFuture<List<T>> zmscoreAsync(String key, Class<T> scoreType, String... members);
|
||||||
|
|||||||
Reference in New Issue
Block a user