|
@@ -31,6 +31,15 @@ public class TemporalUniqueRedisQueue<E> extends AbstractQueue<E> {
|
|
|
"return redis.call('ZADD', KEYS[1], 'NX', 'CH', unpack(ARGV))", Long.class
|
|
|
);
|
|
|
|
|
|
+ /**
|
|
|
+ * 带过期时间Redis队列添加元素脚本(如果存在则忽略)
|
|
|
+ */
|
|
|
+ private static final RedisScript<Long> ADD_DURATION_SCRIPT = new DefaultRedisScript<>(
|
|
|
+ "local value = redis.call('ZADD', KEYS[1], 'NX', 'CH', unpack(ARGV, 2)) " +
|
|
|
+ "if value > 0 and redis.call('TTL', KEYS[1]) < 0 then redis.call('EXPIRE', KEYS[1], ARGV[1]) end " +
|
|
|
+ "return value", Long.class
|
|
|
+ );
|
|
|
+
|
|
|
/**
|
|
|
* Redis队列弹出元素脚本
|
|
|
*/
|
|
@@ -42,16 +51,27 @@ public class TemporalUniqueRedisQueue<E> extends AbstractQueue<E> {
|
|
|
|
|
|
private final long idle;
|
|
|
private final String name;
|
|
|
+ private final long duration;
|
|
|
private final RedisTemplate<String, E> template;
|
|
|
|
|
|
public TemporalUniqueRedisQueue(@NonNull String name, @NonNull Duration idle) {
|
|
|
- this(name, null, idle);
|
|
|
+ this(name, idle, Duration.ofSeconds(-1));
|
|
|
+ }
|
|
|
+
|
|
|
+ public TemporalUniqueRedisQueue(@NonNull String name, @NonNull Duration idle, @NonNull Duration duration) {
|
|
|
+ this(name, null, idle, duration);
|
|
|
}
|
|
|
|
|
|
public TemporalUniqueRedisQueue(@NonNull String name, RedisTemplate<String, E> template, @NonNull Duration idle) {
|
|
|
+ this(name, template, idle, Duration.ofSeconds(-1));
|
|
|
+ }
|
|
|
+
|
|
|
+ public TemporalUniqueRedisQueue(@NonNull String name, RedisTemplate<String, E> template, @NonNull Duration idle,
|
|
|
+ @NonNull Duration duration) {
|
|
|
this.name = name;
|
|
|
- this.idle = idle.toMillis();
|
|
|
+ this.idle = Math.max(idle.toMillis(), 0);
|
|
|
this.template = template;
|
|
|
+ this.duration = Math.max(duration.getSeconds(), -1);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -105,8 +125,8 @@ public class TemporalUniqueRedisQueue<E> extends AbstractQueue<E> {
|
|
|
@Override
|
|
|
public int size() {
|
|
|
long min = 0, max = System.currentTimeMillis();
|
|
|
- Long size = this.template().opsForZSet().count(this.name, min, max);
|
|
|
- return size == null ? 0 : size.intValue();
|
|
|
+ Long count = this.template().opsForZSet().count(this.name, min, max);
|
|
|
+ return count == null ? 0 : count.intValue();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -114,13 +134,16 @@ public class TemporalUniqueRedisQueue<E> extends AbstractQueue<E> {
|
|
|
if (e == null) {
|
|
|
return false;
|
|
|
}
|
|
|
- long timestamp = System.currentTimeMillis();
|
|
|
- RedisTemplate<String, E> template = this.template();
|
|
|
- Object[] args = new Object[]{
|
|
|
- RedisContextHolder.serialize(template.getValueSerializer(), timestamp),
|
|
|
- RedisContextHolder.serialize(template.getValueSerializer(), e)
|
|
|
- };
|
|
|
- Long count = template.execute(ADD_SCRIPT, Collections.singletonList(this.name), args);
|
|
|
+
|
|
|
+ int i = 0;
|
|
|
+ Object[] args = new Object[this.duration > 0 ? 3 : 2];
|
|
|
+ if (this.duration > 0) {
|
|
|
+ args[i++] = this.duration;
|
|
|
+ }
|
|
|
+ args[i++] = System.currentTimeMillis();
|
|
|
+ args[i] = e;
|
|
|
+ RedisScript<Long> script = this.duration > 0 ? ADD_DURATION_SCRIPT : ADD_SCRIPT;
|
|
|
+ Long count = this.template().execute(script, Collections.singletonList(this.name), args);
|
|
|
return count != null && count > 0;
|
|
|
}
|
|
|
|
|
@@ -155,14 +178,17 @@ public class TemporalUniqueRedisQueue<E> extends AbstractQueue<E> {
|
|
|
}
|
|
|
|
|
|
int i = 0;
|
|
|
- Object[] args = new Object[c.size() * 2];
|
|
|
+ Object[] args = new Object[c.size() * 2 + (this.duration > 0 ? 1 : 0)];
|
|
|
+ if (this.duration > 0) {
|
|
|
+ args[i++] = this.duration;
|
|
|
+ }
|
|
|
long timestamp = System.currentTimeMillis();
|
|
|
- RedisTemplate<String, E> template = this.template();
|
|
|
for (E e : c) {
|
|
|
- args[i++] = RedisContextHolder.serialize(template.getValueSerializer(), timestamp++);
|
|
|
- args[i++] = RedisContextHolder.serialize(template.getValueSerializer(), e);
|
|
|
+ args[i++] = timestamp++;
|
|
|
+ args[i++] = e;
|
|
|
}
|
|
|
- Long count = template.execute(ADD_SCRIPT, Collections.singletonList(this.name), args);
|
|
|
+ RedisScript<Long> script = this.duration > 0 ? ADD_DURATION_SCRIPT : ADD_SCRIPT;
|
|
|
+ Long count = this.template().execute(script, Collections.singletonList(this.name), args);
|
|
|
return count != null && count > 0;
|
|
|
}
|
|
|
|
|
@@ -171,6 +197,7 @@ public class TemporalUniqueRedisQueue<E> extends AbstractQueue<E> {
|
|
|
if (o == null) {
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
Long count = this.template().opsForZSet().remove(this.name, o);
|
|
|
return count != null && count > 0;
|
|
|
}
|
|
@@ -180,6 +207,7 @@ public class TemporalUniqueRedisQueue<E> extends AbstractQueue<E> {
|
|
|
if (ObjectUtils.isEmpty(c)) {
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
Long count = this.template().opsForZSet().remove(this.name, c.toArray());
|
|
|
return count != null && count > 0;
|
|
|
}
|