use of org.redisson.api.StreamMessageId in project redisson by redisson.
the class RedissonReliableTopic method addListenerAsync.
@Override
public <M> RFuture<String> addListenerAsync(Class<M> type, MessageListener<M> listener) {
String id = generateId();
listeners.put(id, new Entry(type, listener));
if (subscriberId.get() != null) {
return RedissonPromise.newSucceededFuture(id);
}
if (subscriberId.compareAndSet(null, id)) {
renewExpiration();
StreamMessageId startId = StreamMessageId.ALL;
RFuture<Void> addFuture = commandExecutor.evalWriteNoRetryAsync(getRawName(), StringCodec.INSTANCE, RedisCommands.EVAL_VOID, "local value = redis.call('incr', KEYS[3]); " + "redis.call('zadd', KEYS[4], ARGV[3], ARGV[2]); " + "redis.call('zadd', KEYS[1], value, ARGV[2]); " + "redis.call('hset', KEYS[2], ARGV[2], ARGV[1]); ", Arrays.asList(getSubscribersName(), getMapName(), getCounter(), getTimeout()), startId, id, System.currentTimeMillis() + commandExecutor.getConnectionManager().getCfg().getReliableTopicWatchdogTimeout());
CompletionStage<String> f = addFuture.thenApply(r -> {
poll(id, startId);
return id;
});
return new CompletableFutureWrapper<>(f);
}
return RedissonPromise.newSucceededFuture(id);
}
use of org.redisson.api.StreamMessageId in project redisson by redisson.
the class RedissonReliableTopic method poll.
private void poll(String id, StreamMessageId startId) {
readFuture = commandExecutor.readAsync(getRawName(), new CompositeCodec(StringCodec.INSTANCE, codec), RedisCommands.XREAD_BLOCKING_SINGLE, "BLOCK", 0, "STREAMS", getRawName(), startId);
readFuture.whenComplete((res, ex) -> {
if (readFuture.isCancelled()) {
return;
}
if (ex != null) {
if (ex instanceof RedissonShutdownException) {
return;
}
log.error(ex.getMessage(), ex);
commandExecutor.getConnectionManager().newTimeout(task -> {
poll(id, startId);
}, 1, TimeUnit.SECONDS);
return;
}
commandExecutor.getConnectionManager().getExecutor().execute(() -> {
res.values().forEach(entry -> {
Object m = entry.get("m");
listeners.values().forEach(e -> {
if (e.getType().isInstance(m)) {
((MessageListener<Object>) e.getListener()).onMessage(getRawName(), m);
}
});
});
});
if (listeners.isEmpty()) {
return;
}
StreamMessageId lastId = res.keySet().stream().skip(res.size() - 1).findFirst().get();
long time = System.currentTimeMillis();
RFuture<Boolean> updateFuture = commandExecutor.evalWriteAsync(getRawName(), StringCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "local r = redis.call('zscore', KEYS[2], ARGV[2]); " + "if r ~= false then " + "local value = redis.call('incr', KEYS[4]); " + "redis.call('zadd', KEYS[2], value, ARGV[2]); " + "redis.call('hset', KEYS[3], ARGV[2], ARGV[1]); " + "end; " + "local t = redis.call('zrange', KEYS[5], 0, 0, 'WITHSCORES'); " + "if tonumber(t[2]) < tonumber(ARGV[3]) then " + "redis.call('hdel', KEYS[3], t[1]); " + "redis.call('zrem', KEYS[2], t[1]); " + "redis.call('zrem', KEYS[5], t[1]); " + "end; " + "local v = redis.call('zrange', KEYS[2], 0, 0); " + "local score = redis.call('hget', KEYS[3], v[1]); " + "local range = redis.call('xrange', KEYS[1], score, '+'); " + "if #range == 0 then " + "redis.call('del', KEYS[1]); " + "elseif #range == 1 and range[1][1] == score then " + "redis.call('del', KEYS[1]); " + "else " + "redis.call('xtrim', KEYS[1], 'maxlen', #range); " + "end;" + "return r ~= false; ", Arrays.asList(getRawName(), getSubscribersName(), getMapName(), getCounter(), getTimeout()), lastId, id, time);
updateFuture.whenComplete((re, exc) -> {
if (exc != null) {
if (exc instanceof RedissonShutdownException) {
return;
}
log.error("Unable to update subscriber status", exc);
return;
}
if (!re || listeners.isEmpty()) {
return;
}
poll(id, lastId);
});
});
}
use of org.redisson.api.StreamMessageId in project redisson by redisson.
the class StreamInfoDecoder method createStreamInfoEntry.
private StreamInfo.Entry<Object, Object> createStreamInfoEntry(List<?> fieldValue) {
StreamMessageId id = StreamIdConvertor.INSTANCE.convert(fieldValue.get(0));
Map<Object, Object> data = (Map<Object, Object>) fieldValue.get(1);
return new StreamInfo.Entry<>(id, data);
}
Aggregations