refactoring

pull/4056/head
Nikita Koksharov 3 years ago
parent 7addb77ed1
commit 0c89c54ad2

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
@ -51,9 +52,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doSubscribe(byte[]... channels) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : channels) {
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
@Override
public void onMessage(CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) ch).getName(), channel)) {
@ -67,7 +68,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}
@ -81,9 +82,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doPsubscribe(byte[]... patterns) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : patterns) {
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
@Override
public void onPatternMessage(CharSequence pattern, CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) pattern).getName(), channel)) {
@ -97,7 +98,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
@ -51,9 +52,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doSubscribe(byte[]... channels) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : channels) {
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
@Override
public void onMessage(CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) ch).getName(), channel)) {
@ -67,7 +68,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}
@ -81,9 +82,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doPsubscribe(byte[]... patterns) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : patterns) {
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
@Override
public void onPatternMessage(CharSequence pattern, CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) pattern).getName(), channel)) {
@ -97,7 +98,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
@ -51,9 +52,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doSubscribe(byte[]... channels) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : channels) {
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
@Override
public void onMessage(CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) ch).getName(), channel)) {
@ -67,7 +68,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}
@ -81,9 +82,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doPsubscribe(byte[]... patterns) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : patterns) {
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
@Override
public void onPatternMessage(CharSequence pattern, CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) pattern).getName(), channel)) {
@ -97,7 +98,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
@ -51,9 +52,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doSubscribe(byte[]... channels) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : channels) {
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
@Override
public void onMessage(CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) ch).getName(), channel)) {
@ -67,7 +68,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}
@ -81,9 +82,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doPsubscribe(byte[]... patterns) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : patterns) {
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
@Override
public void onPatternMessage(CharSequence pattern, CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) pattern).getName(), channel)) {
@ -97,7 +98,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}

@ -32,10 +32,9 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@ -98,20 +97,21 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> subscribe(ByteBuffer... channels) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, channels.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : channels) {
ChannelName cn = toChannelName(channel);
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
f.onComplete(listener);
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}
protected ChannelName toChannelName(ByteBuffer channel) {
@ -122,18 +122,19 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> pSubscribe(ByteBuffer... patterns) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, patterns.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : patterns) {
ChannelName cn = toChannelName(channel);
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
f.onComplete(listener);
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
@ -51,9 +52,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doSubscribe(byte[]... channels) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : channels) {
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
@Override
public void onMessage(CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) ch).getName(), channel)) {
@ -67,7 +68,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}
@ -81,9 +82,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doPsubscribe(byte[]... patterns) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : patterns) {
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
@Override
public void onPatternMessage(CharSequence pattern, CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) pattern).getName(), channel)) {
@ -97,7 +98,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}

@ -32,10 +32,9 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@ -98,19 +97,19 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> subscribe(ByteBuffer... channels) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, channels.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : channels) {
ChannelName cn = toChannelName(channel);
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
f.onComplete(listener);
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}
@ -122,18 +121,19 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> pSubscribe(ByteBuffer... patterns) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, patterns.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : patterns) {
ChannelName cn = toChannelName(channel);
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
f.onComplete(listener);
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
@ -51,9 +52,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doSubscribe(byte[]... channels) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : channels) {
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
@Override
public void onMessage(CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) ch).getName(), channel)) {
@ -67,7 +68,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}
@ -81,9 +82,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doPsubscribe(byte[]... patterns) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : patterns) {
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
@Override
public void onPatternMessage(CharSequence pattern, CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) pattern).getName(), channel)) {
@ -97,7 +98,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}

@ -32,10 +32,9 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@ -98,19 +97,19 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> subscribe(ByteBuffer... channels) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, channels.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : channels) {
ChannelName cn = toChannelName(channel);
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
f.onComplete(listener);
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}
@ -122,18 +121,19 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> pSubscribe(ByteBuffer... patterns) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, patterns.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : patterns) {
ChannelName cn = toChannelName(channel);
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
f.onComplete(listener);
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
@ -51,9 +52,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doSubscribe(byte[]... channels) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : channels) {
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
@Override
public void onMessage(CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) ch).getName(), channel)) {
@ -67,7 +68,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}
@ -81,9 +82,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doPsubscribe(byte[]... patterns) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : patterns) {
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
@Override
public void onPatternMessage(CharSequence pattern, CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) pattern).getName(), channel)) {
@ -97,7 +98,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}

@ -32,10 +32,9 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@ -98,19 +97,19 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> subscribe(ByteBuffer... channels) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, channels.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : channels) {
ChannelName cn = toChannelName(channel);
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
f.onComplete(listener);
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}
@ -122,18 +121,19 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> pSubscribe(ByteBuffer... patterns) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, patterns.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : patterns) {
ChannelName cn = toChannelName(channel);
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
f.onComplete(listener);
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
@ -51,9 +52,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doSubscribe(byte[]... channels) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : channels) {
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
@Override
public void onMessage(CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) ch).getName(), channel)) {
@ -67,7 +68,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}
@ -81,9 +82,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doPsubscribe(byte[]... patterns) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : patterns) {
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
@Override
public void onPatternMessage(CharSequence pattern, CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) pattern).getName(), channel)) {
@ -97,7 +98,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}

@ -32,10 +32,9 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
@ -99,19 +98,19 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> subscribe(ByteBuffer... channels) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, channels.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : channels) {
ChannelName cn = toChannelName(channel);
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
f.onComplete(listener);
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}
@ -123,18 +122,19 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> pSubscribe(ByteBuffer... patterns) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, patterns.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : patterns) {
ChannelName cn = toChannelName(channel);
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
f.onComplete(listener);
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
@ -51,9 +52,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doSubscribe(byte[]... channels) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : channels) {
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
@Override
public void onMessage(CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) ch).getName(), channel)) {
@ -67,7 +68,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}
@ -81,9 +82,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doPsubscribe(byte[]... patterns) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : patterns) {
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
@Override
public void onPatternMessage(CharSequence pattern, CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) pattern).getName(), channel)) {
@ -97,7 +98,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}

@ -35,10 +35,9 @@ import reactor.core.publisher.Mono;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
@ -127,19 +126,19 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> subscribe(ByteBuffer... channels) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, channels.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : channels) {
ChannelName cn = toChannelName(channel);
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn, subscriptionListener);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
f.onComplete(listener);
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, cn, subscriptionListener);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}
@ -151,18 +150,19 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
public Mono<Void> pSubscribe(ByteBuffer... patterns) {
monosListener.acquire();
return Mono.defer(() -> {
RedissonPromise<Void> result = new RedissonPromise<>();
result.onComplete((r, ex) -> {
monosListener.release();
});
CountableListener<Void> listener = new CountableListener<>(result, null, patterns.length);
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ByteBuffer channel : patterns) {
ChannelName cn = toChannelName(channel);
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE, subscriptionListener);
f.onComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
f.onComplete(listener);
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(cn, ByteArrayCodec.INSTANCE, subscriptionListener);
f = f.whenComplete((res, e) -> RedissonReactiveSubscription.this.patterns.put(cn, res));
futures.add(f);
}
return Mono.fromFuture(result);
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future = future.whenComplete((r, e) -> {
monosListener.release();
});
return Mono.fromFuture(future);
});
}

@ -15,13 +15,11 @@
*/
package org.redisson.spring.data.connection;
import org.redisson.api.RFuture;
import org.redisson.client.BaseRedisPubSubListener;
import org.redisson.client.ChannelName;
import org.redisson.client.codec.ByteArrayCodec;
import org.redisson.client.protocol.pubsub.PubSubType;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.connection.ConnectionManager;
import org.redisson.pubsub.PubSubConnectionEntry;
import org.redisson.pubsub.PublishSubscribeService;
import org.springframework.data.redis.connection.DefaultMessage;
@ -32,6 +30,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
*
@ -51,9 +50,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doSubscribe(byte[]... channels) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : channels) {
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
CompletableFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, new ChannelName(channel), new BaseRedisPubSubListener() {
@Override
public void onMessage(CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) ch).getName(), channel)) {
@ -67,7 +66,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}
@ -81,9 +80,9 @@ public class RedissonSubscription extends AbstractSubscription {
@Override
protected void doPsubscribe(byte[]... patterns) {
List<RFuture<?>> list = new ArrayList<>();
List<CompletableFuture<?>> list = new ArrayList<>();
for (byte[] channel : patterns) {
RFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
CompletableFuture<Collection<PubSubConnectionEntry>> f = subscribeService.psubscribe(new ChannelName(channel), ByteArrayCodec.INSTANCE, new BaseRedisPubSubListener() {
@Override
public void onPatternMessage(CharSequence pattern, CharSequence ch, Object message) {
if (!Arrays.equals(((ChannelName) pattern).getName(), channel)) {
@ -97,7 +96,7 @@ public class RedissonSubscription extends AbstractSubscription {
});
list.add(f);
}
for (RFuture<?> future : list) {
for (CompletableFuture<?> future : list) {
commandExecutor.syncSubscription(future);
}
}

@ -15,7 +15,7 @@
*/
package org.redisson;
import org.redisson.misc.RPromise;
import java.util.concurrent.CompletableFuture;
/**
*
@ -28,6 +28,6 @@ public interface PubSubEntry<E> {
int release();
RPromise<E> getPromise();
CompletableFuture<E> getPromise();
}

@ -15,15 +15,6 @@
*/
package org.redisson;
import java.util.Arrays;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import org.redisson.api.RCountDownLatch;
@ -31,10 +22,15 @@ import org.redisson.api.RFuture;
import org.redisson.client.codec.LongCodec;
import org.redisson.client.protocol.RedisCommands;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import org.redisson.misc.CompletableFutureWrapper;
import org.redisson.pubsub.CountDownLatchPubSub;
import java.util.Arrays;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
/**
* Distributed alternative to the {@link java.util.concurrent.CountDownLatch}
*
@ -62,66 +58,55 @@ public class RedissonCountDownLatch extends RedissonObject implements RCountDown
return;
}
RFuture<RedissonCountDownLatchEntry> future = subscribe();
CompletableFuture<RedissonCountDownLatchEntry> future = subscribe();
try {
commandExecutor.syncSubscriptionInterrupted(future);
while (getCount() > 0) {
// waiting for open state
future.getNow().getLatch().await();
commandExecutor.getNow(future).getLatch().await();
}
} finally {
unsubscribe(future);
unsubscribe(commandExecutor.getNow(future));
}
}
@Override
public RFuture<Void> awaitAsync() {
RPromise<Void> result = new RedissonPromise<>();
RFuture<Long> countFuture = getCountAsync();
countFuture.onComplete((r, e) -> {
private CompletableFuture<Void> await(RedissonCountDownLatchEntry entry) {
CompletableFuture<Long> countFuture = getCountAsync().toCompletableFuture();
return countFuture.whenComplete((r, e) -> {
if (e != null) {
result.tryFailure(e);
return;
unsubscribe(entry);
}
}).thenCompose(r -> {
if (r == 0) {
unsubscribe(entry);
return CompletableFuture.completedFuture(null);
}
RFuture<RedissonCountDownLatchEntry> subscribeFuture = subscribe();
subscribeFuture.onComplete((res, ex) -> {
if (ex != null) {
result.tryFailure(ex);
return;
}
await(result, subscribeFuture);
CompletableFuture<Void> future = new CompletableFuture<>();
entry.addListener(() -> {
await(entry).whenComplete((res, e) -> {
if (e != null) {
future.completeExceptionally(e);
return;
}
future.complete(res);
});
});
return future;
});
return result;
}
private void await(RPromise<Void> result, RFuture<RedissonCountDownLatchEntry> subscribeFuture) {
if (result.isDone()) {
unsubscribe(subscribeFuture);
return;
}
RFuture<Long> countFuture = getCountAsync();
countFuture.onComplete((r, e) -> {
if (e != null) {
unsubscribe(subscribeFuture);
result.tryFailure(e);
return;
}
if (r == 0) {
unsubscribe(subscribeFuture);
result.trySuccess(null);
return;
}
subscribeFuture.getNow().addListener(() -> {
await(result, subscribeFuture);
});
@Override
public RFuture<Void> awaitAsync() {
CompletableFuture<Long> countFuture = getCountAsync().toCompletableFuture();
CompletableFuture<Void> f = countFuture.thenCompose(r -> {
return subscribe();
}).thenCompose(res -> {
return await(res);
});
return new CompletableFutureWrapper<>(f);
}
@Override
@ -131,7 +116,7 @@ public class RedissonCountDownLatch extends RedissonObject implements RCountDown
if (getCount() == 0) {
return true;
}
RFuture<RedissonCountDownLatchEntry> promise = subscribe();
CompletableFuture<RedissonCountDownLatchEntry> promise = subscribe();
try {
promise.toCompletableFuture().get(time, unit);
} catch (ExecutionException | CancellationException e) {
@ -152,99 +137,73 @@ public class RedissonCountDownLatch extends RedissonObject implements RCountDown
}
current = System.currentTimeMillis();
// waiting for open state
promise.getNow().getLatch().await(remainTime, TimeUnit.MILLISECONDS);
commandExecutor.getNow(promise).getLatch().await(remainTime, TimeUnit.MILLISECONDS);
remainTime -= System.currentTimeMillis() - current;
}
return true;
} finally {
unsubscribe(promise);
unsubscribe(commandExecutor.getNow(promise));
}
}
@Override
public RFuture<Boolean> awaitAsync(long waitTime, TimeUnit unit) {
RPromise<Boolean> result = new RedissonPromise<>();
CompletableFuture<Boolean> result = new CompletableFuture<>();
AtomicLong time = new AtomicLong(unit.toMillis(waitTime));
long currentTime = System.currentTimeMillis();
RFuture<Long> countFuture = getCountAsync();
countFuture.onComplete((r, e) -> {
if (e != null) {
result.tryFailure(e);
return;
}
CompletableFuture<Long> countFuture = getCountAsync().toCompletableFuture();
CompletableFuture<Boolean> f = countFuture.thenCompose(r -> {
long el = System.currentTimeMillis() - currentTime;
time.addAndGet(-el);
if (time.get() <= 0) {
result.trySuccess(false);
return;
return CompletableFuture.completedFuture(false);
}
long current = System.currentTimeMillis();
AtomicReference<Timeout> futureRef = new AtomicReference<>();
RFuture<RedissonCountDownLatchEntry> subscribeFuture = subscribe();
subscribeFuture.onComplete((res, ex) -> {
if (ex != null) {
result.tryFailure(ex);
return;
}
if (futureRef.get() != null) {
futureRef.get().cancel();
}
CompletableFuture<RedissonCountDownLatchEntry> subscribeFuture = subscribe();
return subscribeFuture.thenCompose(entry -> {
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
await(time, result, subscribeFuture);
return await(time, entry);
});
});
return result;
return new CompletableFutureWrapper<>(f);
}
private void await(AtomicLong time, RPromise<Boolean> result, RFuture<RedissonCountDownLatchEntry> subscribeFuture) {
if (result.isDone()) {
unsubscribe(subscribeFuture);
return;
}
private CompletableFuture<Boolean> await(AtomicLong time, RedissonCountDownLatchEntry entry) {
if (time.get() <= 0) {
unsubscribe(subscribeFuture);
result.trySuccess(false);
return;
unsubscribe(entry);
return CompletableFuture.completedFuture(false);
}
long curr = System.currentTimeMillis();
RFuture<Long> countFuture = getCountAsync();
countFuture.onComplete((r, e) -> {
CompletableFuture<Long> countFuture = getCountAsync().toCompletableFuture();
return countFuture.whenComplete((r, e) -> {
if (e != null) {
unsubscribe(subscribeFuture);
result.tryFailure(e);
return;
unsubscribe(entry);
}
}).thenCompose(r -> {
if (r == 0) {
unsubscribe(subscribeFuture);
result.trySuccess(true);
return;
unsubscribe(entry);
return CompletableFuture.completedFuture(true);
}
long el = System.currentTimeMillis() - curr;
time.addAndGet(-el);
if (time.get() <= 0) {
unsubscribe(subscribeFuture);
result.trySuccess(false);
return;
unsubscribe(entry);
return CompletableFuture.completedFuture(false);
}
CompletableFuture<Boolean> future = new CompletableFuture<>();
long current = System.currentTimeMillis();
AtomicBoolean executed = new AtomicBoolean();
RedissonCountDownLatchEntry entry = subscribeFuture.getNow();
AtomicReference<Timeout> futureRef = new AtomicReference<>();
Runnable listener = () -> {
executed.set(true);
@ -255,7 +214,7 @@ public class RedissonCountDownLatch extends RedissonObject implements RCountDown
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
await(time, result, subscribeFuture);
commandExecutor.transfer(await(time, entry), future);
};
entry.addListener(listener);
@ -267,21 +226,23 @@ public class RedissonCountDownLatch extends RedissonObject implements RCountDown
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
await(time, result, subscribeFuture);
commandExecutor.transfer(await(time, entry), future);
}
}
}, time.get(), TimeUnit.MILLISECONDS);
futureRef.set(timeoutFuture);
}
return future;
});
}
private RFuture<RedissonCountDownLatchEntry> subscribe() {
private CompletableFuture<RedissonCountDownLatchEntry> subscribe() {
return pubSub.subscribe(getEntryName(), getChannelName());
}
private void unsubscribe(RFuture<RedissonCountDownLatchEntry> future) {
pubSub.unsubscribe(future.getNow(), getEntryName(), getChannelName());
private void unsubscribe(RedissonCountDownLatchEntry entry) {
pubSub.unsubscribe(entry, getEntryName(), getChannelName());
}
@Override
@ -331,7 +292,7 @@ public class RedissonCountDownLatch extends RedissonObject implements RCountDown
+ "else "
+ "return 0 "
+ "end",
Arrays.<Object>asList(getRawName(), getChannelName()), CountDownLatchPubSub.NEW_COUNT_MESSAGE, count);
Arrays.asList(getRawName(), getChannelName()), CountDownLatchPubSub.NEW_COUNT_MESSAGE, count);
}
@Override
@ -343,7 +304,7 @@ public class RedissonCountDownLatch extends RedissonObject implements RCountDown
+ "else "
+ "return 0 "
+ "end",
Arrays.<Object>asList(getRawName(), getChannelName()), CountDownLatchPubSub.NEW_COUNT_MESSAGE);
Arrays.asList(getRawName(), getChannelName()), CountDownLatchPubSub.NEW_COUNT_MESSAGE);
}
}

@ -15,9 +15,9 @@
*/
package org.redisson;
import org.redisson.misc.RPromise;
import org.redisson.misc.ReclosableLatch;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
public class RedissonCountDownLatchEntry implements PubSubEntry<RedissonCountDownLatchEntry> {
@ -25,10 +25,10 @@ public class RedissonCountDownLatchEntry implements PubSubEntry<RedissonCountDow
private int counter;
private final ReclosableLatch latch;
private final RPromise<RedissonCountDownLatchEntry> promise;
private final CompletableFuture<RedissonCountDownLatchEntry> promise;
private final ConcurrentLinkedQueue<Runnable> listeners = new ConcurrentLinkedQueue<>();
public RedissonCountDownLatchEntry(RPromise<RedissonCountDownLatchEntry> promise) {
public RedissonCountDownLatchEntry(CompletableFuture<RedissonCountDownLatchEntry> promise) {
super();
this.latch = new ReclosableLatch();
this.promise = promise;
@ -42,7 +42,7 @@ public class RedissonCountDownLatchEntry implements PubSubEntry<RedissonCountDow
return --counter;
}
public RPromise<RedissonCountDownLatchEntry> getPromise() {
public CompletableFuture<RedissonCountDownLatchEntry> getPromise() {
return promise;
}

@ -17,6 +17,7 @@ package org.redisson;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
@ -58,14 +59,14 @@ public class RedissonFairLock extends RedissonLock implements RLock {
}
@Override
protected RFuture<RedissonLockEntry> subscribe(long threadId) {
protected CompletableFuture<RedissonLockEntry> subscribe(long threadId) {
return pubSub.subscribe(getEntryName() + ":" + threadId,
getChannelName() + ":" + getLockName(threadId));
}
@Override
protected void unsubscribe(RFuture<RedissonLockEntry> future, long threadId) {
pubSub.unsubscribe(future.getNow(), getEntryName() + ":" + threadId,
protected void unsubscribe(RedissonLockEntry entry, long threadId) {
pubSub.unsubscribe(entry, getEntryName() + ":" + threadId,
getChannelName() + ":" + getLockName(threadId));
}
@ -94,7 +95,7 @@ public class RedissonFairLock extends RedissonLock implements RLock {
// remove the thread from the queue and timeouts set
"redis.call('zrem', KEYS[2], ARGV[1]);" +
"redis.call('lrem', KEYS[1], 0, ARGV[1]);",
Arrays.<Object>asList(threadsQueueName, timeoutSetName),
Arrays.asList(threadsQueueName, timeoutSetName),
getLockName(threadId), wait);
}
@ -335,7 +336,7 @@ public class RedissonFairLock extends RedissonLock implements RLock {
"return 1; " +
"end; " +
"return 0;",
Arrays.<Object>asList(getRawName(), threadsQueueName, timeoutSetName, getChannelName()),
Arrays.asList(getRawName(), threadsQueueName, timeoutSetName, getChannelName()),
LockPubSub.UNLOCK_MESSAGE, System.currentTimeMillis());
}

@ -29,6 +29,7 @@ import org.redisson.pubsub.LockPubSub;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@ -102,7 +103,7 @@ public class RedissonLock extends RedissonBaseLock {
return;
}
RFuture<RedissonLockEntry> future = subscribe(threadId);
CompletableFuture<RedissonLockEntry> future = subscribe(threadId);
if (interruptibly) {
commandExecutor.syncSubscriptionInterrupted(future);
} else {
@ -120,23 +121,23 @@ public class RedissonLock extends RedissonBaseLock {
// waiting for message
if (ttl >= 0) {
try {
future.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
commandExecutor.getNow(future).getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
if (interruptibly) {
throw e;
}
future.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
commandExecutor.getNow(future).getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
}
} else {
if (interruptibly) {
future.getNow().getLatch().acquire();
commandExecutor.getNow(future).getLatch().acquire();
} else {
future.getNow().getLatch().acquireUninterruptibly();
commandExecutor.getNow(future).getLatch().acquireUninterruptibly();
}
}
}
} finally {
unsubscribe(future, threadId);
unsubscribe(commandExecutor.getNow(future), threadId);
}
// get(lockAsync(leaseTime, unit));
}
@ -235,14 +236,14 @@ public class RedissonLock extends RedissonBaseLock {
}
current = System.currentTimeMillis();
RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
CompletableFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
try {
subscribeFuture.toCompletableFuture().get(time, TimeUnit.MILLISECONDS);
} catch (ExecutionException | TimeoutException e) {
if (!subscribeFuture.cancel(false)) {
subscribeFuture.onComplete((res, ex) -> {
subscribeFuture.whenComplete((res, ex) -> {
if (ex == null) {
unsubscribe(subscribeFuture, threadId);
unsubscribe(res, threadId);
}
});
}
@ -274,9 +275,9 @@ public class RedissonLock extends RedissonBaseLock {
// waiting for message
currentTime = System.currentTimeMillis();
if (ttl >= 0 && ttl < time) {
subscribeFuture.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
commandExecutor.getNow(subscribeFuture).getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
} else {
subscribeFuture.getNow().getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);
commandExecutor.getNow(subscribeFuture).getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);
}
time -= System.currentTimeMillis() - currentTime;
@ -286,17 +287,17 @@ public class RedissonLock extends RedissonBaseLock {
}
}
} finally {
unsubscribe(subscribeFuture, threadId);
unsubscribe(commandExecutor.getNow(subscribeFuture), threadId);
}
// return get(tryLockAsync(waitTime, leaseTime, unit));
}
protected RFuture<RedissonLockEntry> subscribe(long threadId) {
protected CompletableFuture<RedissonLockEntry> subscribe(long threadId) {
return pubSub.subscribe(getEntryName(), getChannelName());
}
protected void unsubscribe(RFuture<RedissonLockEntry> future, long threadId) {
pubSub.unsubscribe(future.getNow(), getEntryName(), getChannelName());
protected void unsubscribe(RedissonLockEntry entry, long threadId) {
pubSub.unsubscribe(entry, getEntryName(), getChannelName());
}
@Override
@ -397,14 +398,14 @@ public class RedissonLock extends RedissonBaseLock {
return;
}
RFuture<RedissonLockEntry> subscribeFuture = subscribe(currentThreadId);
subscribeFuture.onComplete((res, ex) -> {
CompletableFuture<RedissonLockEntry> subscribeFuture = subscribe(currentThreadId);
subscribeFuture.whenComplete((res, ex) -> {
if (ex != null) {
result.tryFailure(ex);
return;
}
lockAsync(leaseTime, unit, subscribeFuture, result, currentThreadId);
lockAsync(leaseTime, unit, res, result, currentThreadId);
});
});
@ -412,27 +413,26 @@ public class RedissonLock extends RedissonBaseLock {
}
private void lockAsync(long leaseTime, TimeUnit unit,
RFuture<RedissonLockEntry> subscribeFuture, RPromise<Void> result, long currentThreadId) {
RedissonLockEntry entry, RPromise<Void> result, long currentThreadId) {
RFuture<Long> ttlFuture = tryAcquireAsync(-1, leaseTime, unit, currentThreadId);
ttlFuture.onComplete((ttl, e) -> {
if (e != null) {
unsubscribe(subscribeFuture, currentThreadId);
unsubscribe(entry, currentThreadId);
result.tryFailure(e);
return;
}
// lock acquired
if (ttl == null) {
unsubscribe(subscribeFuture, currentThreadId);
unsubscribe(entry, currentThreadId);
if (!result.trySuccess(null)) {
unlockAsync(currentThreadId);
}
return;
}
RedissonLockEntry entry = subscribeFuture.getNow();
if (entry.getLatch().tryAcquire()) {
lockAsync(leaseTime, unit, subscribeFuture, result, currentThreadId);
lockAsync(leaseTime, unit, entry, result, currentThreadId);
} else {
// waiting for message
AtomicReference<Timeout> futureRef = new AtomicReference<Timeout>();
@ -440,7 +440,7 @@ public class RedissonLock extends RedissonBaseLock {
if (futureRef.get() != null) {
futureRef.get().cancel();
}
lockAsync(leaseTime, unit, subscribeFuture, result, currentThreadId);
lockAsync(leaseTime, unit, entry, result, currentThreadId);
};
entry.addListener(listener);
@ -450,7 +450,7 @@ public class RedissonLock extends RedissonBaseLock {
@Override
public void run(Timeout timeout) throws Exception {
if (entry.removeListener(listener)) {
lockAsync(leaseTime, unit, subscribeFuture, result, currentThreadId);
lockAsync(leaseTime, unit, entry, result, currentThreadId);
}
}
}, ttl, TimeUnit.MILLISECONDS);
@ -513,8 +513,8 @@ public class RedissonLock extends RedissonBaseLock {
long current = System.currentTimeMillis();
AtomicReference<Timeout> futureRef = new AtomicReference<Timeout>();
RFuture<RedissonLockEntry> subscribeFuture = subscribe(currentThreadId);
subscribeFuture.onComplete((r, ex) -> {
CompletableFuture<RedissonLockEntry> subscribeFuture = subscribe(currentThreadId);
subscribeFuture.whenComplete((r, ex) -> {
if (ex != null) {
result.tryFailure(ex);
return;
@ -527,7 +527,7 @@ public class RedissonLock extends RedissonBaseLock {
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
tryLockAsync(time, waitTime, leaseTime, unit, subscribeFuture, result, currentThreadId);
tryLockAsync(time, waitTime, leaseTime, unit, r, result, currentThreadId);
});
if (!subscribeFuture.isDone()) {
Timeout scheduledFuture = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {
@ -558,14 +558,14 @@ public class RedissonLock extends RedissonBaseLock {
}
private void tryLockAsync(AtomicLong time, long waitTime, long leaseTime, TimeUnit unit,
RFuture<RedissonLockEntry> subscribeFuture, RPromise<Boolean> result, long currentThreadId) {
RedissonLockEntry entry, RPromise<Boolean> result, long currentThreadId) {
if (result.isDone()) {
unsubscribe(subscribeFuture, currentThreadId);
unsubscribe(entry, currentThreadId);
return;
}
if (time.get() <= 0) {
unsubscribe(subscribeFuture, currentThreadId);
unsubscribe(entry, currentThreadId);
trySuccessFalse(currentThreadId, result);
return;
}
@ -574,14 +574,14 @@ public class RedissonLock extends RedissonBaseLock {
RFuture<Long> ttlFuture = tryAcquireAsync(waitTime, leaseTime, unit, currentThreadId);
ttlFuture.onComplete((ttl, e) -> {
if (e != null) {
unsubscribe(subscribeFuture, currentThreadId);
unsubscribe(entry, currentThreadId);
result.tryFailure(e);
return;
}
// lock acquired
if (ttl == null) {
unsubscribe(subscribeFuture, currentThreadId);
unsubscribe(entry, currentThreadId);
if (!result.trySuccess(true)) {
unlockAsync(currentThreadId);
}
@ -592,16 +592,15 @@ public class RedissonLock extends RedissonBaseLock {
time.addAndGet(-el);
if (time.get() <= 0) {
unsubscribe(subscribeFuture, currentThreadId);
unsubscribe(entry, currentThreadId);
trySuccessFalse(currentThreadId, result);
return;
}
// waiting for message
long current = System.currentTimeMillis();
RedissonLockEntry entry = subscribeFuture.getNow();
if (entry.getLatch().tryAcquire()) {
tryLockAsync(time, waitTime, leaseTime, unit, subscribeFuture, result, currentThreadId);
tryLockAsync(time, waitTime, leaseTime, unit, entry, result, currentThreadId);
} else {
AtomicBoolean executed = new AtomicBoolean();
AtomicReference<Timeout> futureRef = new AtomicReference<Timeout>();
@ -614,7 +613,7 @@ public class RedissonLock extends RedissonBaseLock {
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
tryLockAsync(time, waitTime, leaseTime, unit, subscribeFuture, result, currentThreadId);
tryLockAsync(time, waitTime, leaseTime, unit, entry, result, currentThreadId);
};
entry.addListener(listener);
@ -630,7 +629,7 @@ public class RedissonLock extends RedissonBaseLock {
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
tryLockAsync(time, waitTime, leaseTime, unit, subscribeFuture, result, currentThreadId);
tryLockAsync(time, waitTime, leaseTime, unit, entry, result, currentThreadId);
}
}
}, t, TimeUnit.MILLISECONDS);

@ -15,11 +15,10 @@
*/
package org.redisson;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Semaphore;
import org.redisson.misc.RPromise;
/**
*
* @author Nikita Koksharov
@ -30,10 +29,10 @@ public class RedissonLockEntry implements PubSubEntry<RedissonLockEntry> {
private volatile int counter;
private final Semaphore latch;
private final RPromise<RedissonLockEntry> promise;
private final CompletableFuture<RedissonLockEntry> promise;
private final ConcurrentLinkedQueue<Runnable> listeners = new ConcurrentLinkedQueue<Runnable>();
public RedissonLockEntry(RPromise<RedissonLockEntry> promise) {
public RedissonLockEntry(CompletableFuture<RedissonLockEntry> promise) {
super();
this.latch = new Semaphore(0);
this.promise = promise;
@ -51,7 +50,7 @@ public class RedissonLockEntry implements PubSubEntry<RedissonLockEntry> {
return --counter;
}
public RPromise<RedissonLockEntry> getPromise() {
public CompletableFuture<RedissonLockEntry> getPromise() {
return promise;
}

@ -17,7 +17,6 @@ package org.redisson;
import io.netty.buffer.ByteBufUtil;
import org.redisson.api.RExecutorService;
import org.redisson.api.RFuture;
import org.redisson.api.RedissonClient;
import org.redisson.api.WorkerOptions;
import org.redisson.client.RedisConnection;
@ -32,6 +31,7 @@ import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Map.Entry;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@ -167,7 +167,7 @@ public final class RedissonNode {
private void retrieveAddresses() {
ConnectionManager connectionManager = ((Redisson) redisson).getConnectionManager();
for (MasterSlaveEntry entry : connectionManager.getEntrySet()) {
RFuture<RedisConnection> readFuture = entry.connectionReadOp(null);
CompletionStage<RedisConnection> readFuture = entry.connectionReadOp(null);
RedisConnection readConnection = null;
try {
readConnection = readFuture.toCompletableFuture().get(connectionManager.getConfig().getConnectTimeout(), TimeUnit.MILLISECONDS);
@ -183,7 +183,7 @@ public final class RedissonNode {
return;
}
RFuture<RedisConnection> writeFuture = entry.connectionWriteOp(null);
CompletionStage<RedisConnection> writeFuture = entry.connectionWriteOp(null);
RedisConnection writeConnection = null;
try {
writeConnection = writeFuture.toCompletableFuture().get(connectionManager.getConfig().getConnectTimeout(), TimeUnit.MILLISECONDS);

@ -26,8 +26,7 @@ import org.redisson.client.codec.Codec;
import org.redisson.client.protocol.pubsub.PubSubType;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.config.MasterSlaveServersConfig;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import org.redisson.misc.CompletableFutureWrapper;
import org.redisson.pubsub.AsyncSemaphore;
import org.redisson.pubsub.PubSubConnectionEntry;
import org.redisson.pubsub.PublishSubscribeService;
@ -35,6 +34,7 @@ import org.redisson.pubsub.PublishSubscribeService;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* Distributed topic implementation. Messages are delivered to all message listeners across Redis cluster.
@ -74,7 +74,7 @@ public class RedissonPatternTopic implements RPatternTopic {
}
private int addListener(RedisPubSubListener<?> pubSubListener) {
RFuture<Collection<PubSubConnectionEntry>> future = subscribeService.psubscribe(channelName, codec, pubSubListener);
CompletableFuture<Collection<PubSubConnectionEntry>> future = subscribeService.psubscribe(channelName, codec, pubSubListener);
commandExecutor.syncSubscription(future);
return System.identityHashCode(pubSubListener);
}
@ -92,17 +92,11 @@ public class RedissonPatternTopic implements RPatternTopic {
}
private RFuture<Integer> addListenerAsync(RedisPubSubListener<?> pubSubListener) {
RFuture<Collection<PubSubConnectionEntry>> future = subscribeService.psubscribe(channelName, codec, pubSubListener);
RPromise<Integer> result = new RedissonPromise<Integer>();
future.onComplete((res, e) -> {
if (e != null) {
result.tryFailure(e);
return;
}
result.trySuccess(System.identityHashCode(pubSubListener));
CompletableFuture<Collection<PubSubConnectionEntry>> future = subscribeService.psubscribe(channelName, codec, pubSubListener);
CompletableFuture<Integer> f = future.thenApply(res -> {
return System.identityHashCode(pubSubListener);
});
return result;
return new CompletableFutureWrapper<>(f);
}
protected void acquire(AsyncSemaphore semaphore) {
@ -115,12 +109,13 @@ public class RedissonPatternTopic implements RPatternTopic {
@Override
public RFuture<Void> removeListenerAsync(int listenerId) {
return subscribeService.removeListenerAsync(PubSubType.PUNSUBSCRIBE, channelName, listenerId);
CompletableFuture<Void> f = subscribeService.removeListenerAsync(PubSubType.PUNSUBSCRIBE, channelName, listenerId);
return new CompletableFutureWrapper<>(f);
}
@Override
public void removeListener(int listenerId) {
commandExecutor.syncSubscription(removeListenerAsync(listenerId));
commandExecutor.syncSubscription(removeListenerAsync(listenerId).toCompletableFuture());
}
@Override
@ -142,7 +137,7 @@ public class RedissonPatternTopic implements RPatternTopic {
@Override
public void removeListener(PatternMessageListener<?> listener) {
RFuture<Void> future = subscribeService.removeListenerAsync(PubSubType.PUNSUBSCRIBE, channelName, listener);
CompletableFuture<Void> future = subscribeService.removeListenerAsync(PubSubType.PUNSUBSCRIBE, channelName, listener);
commandExecutor.syncSubscription(future);
}

@ -15,15 +15,9 @@
*/
package org.redisson;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import io.netty.buffer.ByteBufUtil;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import org.redisson.api.RFuture;
import org.redisson.api.RPermitExpirableSemaphore;
import org.redisson.client.codec.LongCodec;
@ -33,9 +27,11 @@ import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import org.redisson.pubsub.SemaphorePubSub;
import io.netty.buffer.ByteBufUtil;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
/**
*
@ -91,7 +87,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
return permitId;
}
RFuture<RedissonLockEntry> future = subscribe();
CompletableFuture<RedissonLockEntry> future = subscribe();
commandExecutor.syncSubscriptionInterrupted(future);
try {
while (true) {
@ -108,13 +104,13 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
}
if (nearestTimeout != null) {
future.getNow().getLatch().tryAcquire(permits, nearestTimeout, TimeUnit.MILLISECONDS);
commandExecutor.getNow(future).getLatch().tryAcquire(permits, nearestTimeout, TimeUnit.MILLISECONDS);
} else {
future.getNow().getLatch().acquire(permits);
commandExecutor.getNow(future).getLatch().acquire(permits);
}
}
} finally {
unsubscribe(future);
unsubscribe(commandExecutor.getNow(future));
}
// return get(acquireAsync(permits, ttl, timeUnit));
}
@ -140,27 +136,27 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
return;
}
RFuture<RedissonLockEntry> subscribeFuture = subscribe();
subscribeFuture.onComplete((res, ex) -> {
CompletableFuture<RedissonLockEntry> subscribeFuture = subscribe();
subscribeFuture.whenComplete((res, ex) -> {
if (ex != null) {
result.tryFailure(ex);
return;
}
acquireAsync(permits, subscribeFuture, result, ttl, timeUnit);
acquireAsync(permits, res, result, ttl, timeUnit);
});
});
return result;
}
private void tryAcquireAsync(AtomicLong time, int permits, RFuture<RedissonLockEntry> subscribeFuture, RPromise<String> result, long ttl, TimeUnit timeUnit) {
private void tryAcquireAsync(AtomicLong time, int permits, RedissonLockEntry entry, RPromise<String> result, long ttl, TimeUnit timeUnit) {
if (result.isDone()) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
return;
}
if (time.get() <= 0) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
result.trySuccess(null);
return;
}
@ -170,7 +166,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
RFuture<String> tryAcquireFuture = tryAcquireAsync(permits, timeoutDate);
tryAcquireFuture.onComplete((permitId, e) -> {
if (e != null) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
result.tryFailure(e);
return;
}
@ -178,7 +174,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
Long nearestTimeout;
if (permitId != null) {
if (!permitId.startsWith(":")) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
if (!result.trySuccess(permitId)) {
releaseAsync(permitId);
}
@ -194,16 +190,15 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
time.addAndGet(-el);
if (time.get() <= 0) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
result.trySuccess(null);
return;
}
// waiting for message
long current = System.currentTimeMillis();
RedissonLockEntry entry = subscribeFuture.getNow();
if (entry.getLatch().tryAcquire()) {
tryAcquireAsync(time, permits, subscribeFuture, result, ttl, timeUnit);
tryAcquireAsync(time, permits, entry, result, ttl, timeUnit);
} else {
AtomicReference<Timeout> waitTimeoutFutureRef = new AtomicReference<Timeout>();
@ -219,7 +214,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
tryAcquireAsync(time, permits, subscribeFuture, result, ttl, timeUnit);
tryAcquireAsync(time, permits, entry, result, ttl, timeUnit);
}
}, nearestTimeout, TimeUnit.MILLISECONDS);
} else {
@ -239,7 +234,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
tryAcquireAsync(time, permits, subscribeFuture, result, ttl, timeUnit);
tryAcquireAsync(time, permits, entry, result, ttl, timeUnit);
};
entry.addListener(listener);
@ -255,7 +250,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
tryAcquireAsync(time, permits, subscribeFuture, result, ttl, timeUnit);
tryAcquireAsync(time, permits, entry, result, ttl, timeUnit);
}
}
}, t, TimeUnit.MILLISECONDS);
@ -265,9 +260,9 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
}
private void acquireAsync(int permits, RFuture<RedissonLockEntry> subscribeFuture, RPromise<String> result, long ttl, TimeUnit timeUnit) {
private void acquireAsync(int permits, RedissonLockEntry entry, RPromise<String> result, long ttl, TimeUnit timeUnit) {
if (result.isDone()) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
return;
}
@ -275,7 +270,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
RFuture<String> tryAcquireFuture = tryAcquireAsync(permits, timeoutDate);
tryAcquireFuture.onComplete((permitId, e) -> {
if (e != null) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
result.tryFailure(e);
return;
}
@ -283,7 +278,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
Long nearestTimeout;
if (permitId != null) {
if (!permitId.startsWith(":")) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
if (!result.trySuccess(permitId)) {
releaseAsync(permitId);
}
@ -295,16 +290,15 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
nearestTimeout = null;
}
RedissonLockEntry entry = subscribeFuture.getNow();
if (entry.getLatch().tryAcquire(permits)) {
acquireAsync(permits, subscribeFuture, result, ttl, timeUnit);
acquireAsync(permits, entry, result, ttl, timeUnit);
} else {
Timeout scheduledFuture;
if (nearestTimeout != null) {
scheduledFuture = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {
@Override
public void run(Timeout timeout) throws Exception {
acquireAsync(permits, subscribeFuture, result, ttl, timeUnit);
acquireAsync(permits, entry, result, ttl, timeUnit);
}
}, nearestTimeout, TimeUnit.MILLISECONDS);
} else {
@ -316,7 +310,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
entry.getLatch().release();
return;
}
acquireAsync(permits, subscribeFuture, result, ttl, timeUnit);
acquireAsync(permits, entry, result, ttl, timeUnit);
};
entry.addListener(listener);
}
@ -344,6 +338,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
return nonExpirableTimeout;
}
@Override
public RFuture<String> tryAcquireAsync() {
RPromise<String> result = new RedissonPromise<String>();
RFuture<String> future = tryAcquireAsync(1, nonExpirableTimeout);
@ -434,9 +429,10 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
}
current = System.currentTimeMillis();
RFuture<RedissonLockEntry> future = subscribe();
CompletableFuture<RedissonLockEntry> future = subscribe();
RedissonLockEntry entry;
try {
future.toCompletableFuture().get(time, TimeUnit.MILLISECONDS);
entry = future.get(time, TimeUnit.MILLISECONDS);
} catch (ExecutionException | TimeoutException e) {
return null;
}
@ -470,9 +466,9 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
current = System.currentTimeMillis();
if (nearestTimeout != null) {
future.getNow().getLatch().tryAcquire(permits, Math.min(time, nearestTimeout), TimeUnit.MILLISECONDS);
entry.getLatch().tryAcquire(permits, Math.min(time, nearestTimeout), TimeUnit.MILLISECONDS);
} else {
future.getNow().getLatch().tryAcquire(permits, time, TimeUnit.MILLISECONDS);
entry.getLatch().tryAcquire(permits, time, TimeUnit.MILLISECONDS);
}
long elapsed = System.currentTimeMillis() - current;
@ -482,7 +478,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
}
}
} finally {
unsubscribe(future);
unsubscribe(entry);
}
// return get(tryAcquireAsync(permits, waitTime, ttl, unit));
}
@ -516,8 +512,8 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
long current = System.currentTimeMillis();
AtomicReference<Timeout> futureRef = new AtomicReference<Timeout>();
RFuture<RedissonLockEntry> subscribeFuture = subscribe();
subscribeFuture.onComplete((r, ex) -> {
CompletableFuture<RedissonLockEntry> subscribeFuture = subscribe();
subscribeFuture.whenComplete((r, ex) -> {
if (ex != null) {
result.tryFailure(ex);
return;
@ -530,7 +526,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
tryAcquireAsync(time, permits, subscribeFuture, result, ttl, timeUnit);
tryAcquireAsync(time, permits, r, result, ttl, timeUnit);
});
if (!subscribeFuture.isDone()) {
@ -549,12 +545,12 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
return result;
}
private RFuture<RedissonLockEntry> subscribe() {
private CompletableFuture<RedissonLockEntry> subscribe() {
return semaphorePubSub.subscribe(getRawName(), getChannelName());
}
private void unsubscribe(RFuture<RedissonLockEntry> future) {
semaphorePubSub.unsubscribe(future.getNow(), getRawName(), getChannelName());
private void unsubscribe(RedissonLockEntry entry) {
semaphorePubSub.unsubscribe(entry, getRawName(), getChannelName());
}
@Override

@ -26,8 +26,6 @@ import org.redisson.command.CommandAsyncExecutor;
import org.redisson.connection.MasterSlaveEntry;
import org.redisson.connection.NodeSource;
import org.redisson.misc.CompletableFutureWrapper;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@ -66,15 +64,13 @@ public class RedissonScript implements RScript {
Collection<MasterSlaveEntry> nodes = commandExecutor.getConnectionManager().getEntrySet();
List<CompletableFuture<String>> futures = new ArrayList<>();
nodes.forEach(e -> {
RPromise<String> promise = new RedissonPromise<>();
commandExecutor.async(false, new NodeSource(e), codec, RedisCommands.SCRIPT_LOAD,
new Object[]{luaScript}, promise, true, false);
RFuture<String> promise = commandExecutor.async(false, new NodeSource(e),
codec, RedisCommands.SCRIPT_LOAD, new Object[]{luaScript}, true, false);
futures.add(promise.toCompletableFuture());
e.getAllEntries().stream().filter(c -> c.getNodeType() == NodeType.SLAVE).forEach(c -> {
RPromise<String> slavePromise = new RedissonPromise<>();
commandExecutor.async(true, new NodeSource(e, c.getClient()), codec, RedisCommands.SCRIPT_LOAD,
new Object[]{luaScript}, slavePromise, true, false);
RFuture<String> slavePromise = commandExecutor.async(true, new NodeSource(e, c.getClient()),
codec, RedisCommands.SCRIPT_LOAD, new Object[]{luaScript}, true, false);
futures.add(slavePromise.toCompletableFuture());
});
});
@ -157,7 +153,7 @@ public class RedissonScript implements RScript {
@Override
public RFuture<List<Boolean>> scriptExistsAsync(final String... shaDigests) {
return commandExecutor.writeAllAsync(RedisCommands.SCRIPT_EXISTS, new SlotCallback<List<Boolean>, List<Boolean>>() {
volatile List<Boolean> result = new ArrayList<Boolean>(shaDigests.length);
volatile List<Boolean> result = new ArrayList<>(shaDigests.length);
@Override
public synchronized void onSlotResult(List<Boolean> result) {
for (int i = 0; i < result.size(); i++) {
@ -170,7 +166,7 @@ public class RedissonScript implements RScript {
@Override
public List<Boolean> onFinish() {
return new ArrayList<Boolean>(result);
return new ArrayList<>(result);
}
}, (Object[]) shaDigests);
}

@ -31,10 +31,7 @@ import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
@ -83,7 +80,7 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
return;
}
RFuture<RedissonLockEntry> future = subscribe();
CompletableFuture<RedissonLockEntry> future = subscribe();
commandExecutor.syncSubscriptionInterrupted(future);
try {
while (true) {
@ -91,10 +88,10 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
return;
}
future.getNow().getLatch().acquire();
commandExecutor.getNow(future).getLatch().acquire();
}
} finally {
unsubscribe(future);
unsubscribe(commandExecutor.getNow(future));
}
// get(acquireAsync(permits));
}
@ -121,27 +118,27 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
return;
}
RFuture<RedissonLockEntry> subscribeFuture = subscribe();
subscribeFuture.onComplete((r, e1) -> {
CompletableFuture<RedissonLockEntry> subscribeFuture = subscribe();
subscribeFuture.whenComplete((r, e1) -> {
if (e1 != null) {
result.tryFailure(e1);
return;
}
acquireAsync(permits, subscribeFuture, result);
acquireAsync(permits, r, result);
});
});
return result;
}
private void tryAcquireAsync(AtomicLong time, int permits, RFuture<RedissonLockEntry> subscribeFuture, RPromise<Boolean> result) {
private void tryAcquireAsync(AtomicLong time, int permits, RedissonLockEntry entry, RPromise<Boolean> result) {
if (result.isDone()) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
return;
}
if (time.get() <= 0) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
result.trySuccess(false);
return;
}
@ -150,13 +147,13 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
RFuture<Boolean> tryAcquireFuture = tryAcquireAsync(permits);
tryAcquireFuture.onComplete((res, e) -> {
if (e != null) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
result.tryFailure(e);
return;
}
if (res) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
if (!result.trySuccess(true)) {
releaseAsync(permits);
}
@ -167,16 +164,15 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
time.addAndGet(-el);
if (time.get() <= 0) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
result.trySuccess(false);
return;
}
// waiting for message
long current = System.currentTimeMillis();
RedissonLockEntry entry = subscribeFuture.getNow();
if (entry.getLatch().tryAcquire()) {
tryAcquireAsync(time, permits, subscribeFuture, result);
tryAcquireAsync(time, permits, entry, result);
} else {
AtomicBoolean executed = new AtomicBoolean();
AtomicReference<Timeout> futureRef = new AtomicReference<Timeout>();
@ -189,7 +185,7 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
tryAcquireAsync(time, permits, subscribeFuture, result);
tryAcquireAsync(time, permits, entry, result);
};
entry.addListener(listener);
@ -202,7 +198,7 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
long elapsed = System.currentTimeMillis() - current;
time.addAndGet(-elapsed);
tryAcquireAsync(time, permits, subscribeFuture, result);
tryAcquireAsync(time, permits, entry, result);
}
}
}, t, TimeUnit.MILLISECONDS);
@ -212,34 +208,33 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
});
}
private void acquireAsync(int permits, RFuture<RedissonLockEntry> subscribeFuture, RPromise<Void> result) {
private void acquireAsync(int permits, RedissonLockEntry entry, RPromise<Void> result) {
if (result.isDone()) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
return;
}
RFuture<Boolean> tryAcquireFuture = tryAcquireAsync(permits);
tryAcquireFuture.onComplete((res, e) -> {
if (e != null) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
result.tryFailure(e);
return;
}
if (res) {
unsubscribe(subscribeFuture);
unsubscribe(entry);
if (!result.trySuccess(null)) {
releaseAsync(permits);
}
return;
}
RedissonLockEntry entry = subscribeFuture.getNow();
if (entry.getLatch().tryAcquire()) {
acquireAsync(permits, subscribeFuture, result);
acquireAsync(permits, entry, result);
} else {
entry.addListener(() -> {
acquireAsync(permits, subscribeFuture, result);
acquireAsync(permits, entry, result);
});
}
});
@ -303,9 +298,10 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
}
current = System.currentTimeMillis();
RFuture<RedissonLockEntry> future = subscribe();
CompletableFuture<RedissonLockEntry> future = subscribe();
RedissonLockEntry entry;
try {
future.toCompletableFuture().get(time, TimeUnit.MILLISECONDS);
entry = future.get(time, TimeUnit.MILLISECONDS);
} catch (ExecutionException | CancellationException | TimeoutException e) {
log.debug("unable to subscribe for permits acquisition, permits: {}, name: {}", permits, getName());
return false;
@ -335,7 +331,7 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
current = System.currentTimeMillis();
log.debug("wait for acquisition, permits: {}, wait-time(ms): {}, name: {}", permits, time, getName());
future.getNow().getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);
entry.getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);
time -= System.currentTimeMillis() - current;
if (time <= 0) {
@ -344,7 +340,7 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
}
}
} finally {
unsubscribe(future);
unsubscribe(entry);
}
// return get(tryAcquireAsync(permits, waitTime, unit));
}
@ -378,8 +374,8 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
long current = System.currentTimeMillis();
AtomicReference<Timeout> futureRef = new AtomicReference<Timeout>();
RFuture<RedissonLockEntry> subscribeFuture = subscribe();
subscribeFuture.onComplete((r, ex) -> {
CompletableFuture<RedissonLockEntry> subscribeFuture = subscribe();
subscribeFuture.whenComplete((r, ex) -> {
if (ex != null) {
result.tryFailure(ex);
return;
@ -393,12 +389,12 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
time.addAndGet(-elapsed);
if (time.get() < 0) {
unsubscribe(subscribeFuture);
unsubscribe(r);
result.trySuccess(false);
return;
}
tryAcquireAsync(time, permits, subscribeFuture, result);
tryAcquireAsync(time, permits, r, result);
});
if (!subscribeFuture.isDone()) {
@ -416,12 +412,12 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
return result;
}
private RFuture<RedissonLockEntry> subscribe() {
private CompletableFuture<RedissonLockEntry> subscribe() {
return semaphorePubSub.subscribe(getRawName(), getChannelName());
}
private void unsubscribe(RFuture<RedissonLockEntry> future) {
semaphorePubSub.unsubscribe(future.getNow(), getRawName(), getChannelName());
private void unsubscribe(RedissonLockEntry entry) {
semaphorePubSub.unsubscribe(entry, getRawName(), getChannelName());
}
@Override

@ -30,14 +30,14 @@ import org.redisson.client.protocol.RedisCommands;
import org.redisson.client.protocol.pubsub.PubSubType;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.config.MasterSlaveServersConfig;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import org.redisson.misc.CompletableFutureWrapper;
import org.redisson.pubsub.AsyncSemaphore;
import org.redisson.pubsub.PubSubConnectionEntry;
import org.redisson.pubsub.PublishSubscribeService;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* Distributed topic implementation. Messages are delivered to all message listeners across Redis cluster.
@ -104,15 +104,15 @@ public class RedissonTopic implements RTopic {
@Override
public int addListener(StatusListener listener) {
RFuture<Integer> future = addListenerAsync(listener);
commandExecutor.syncSubscription(future);
return future.getNow();
commandExecutor.syncSubscription(future.toCompletableFuture());
return commandExecutor.getNow(future.toCompletableFuture());
};
@Override
public <M> int addListener(Class<M> type, MessageListener<? extends M> listener) {
RFuture<Integer> future = addListenerAsync(type, (MessageListener<M>) listener);
commandExecutor.syncSubscription(future);
return future.getNow();
commandExecutor.syncSubscription(future.toCompletableFuture());
return commandExecutor.getNow(future.toCompletableFuture());
}
@Override
@ -128,22 +128,11 @@ public class RedissonTopic implements RTopic {
}
protected RFuture<Integer> addListenerAsync(RedisPubSubListener<?> pubSubListener) {
RFuture<PubSubConnectionEntry> future = subscribeService.subscribe(codec, channelName, pubSubListener);
RPromise<Integer> result = new RedissonPromise<>();
result.onComplete((res, e) -> {
if (e != null) {
((RPromise<PubSubConnectionEntry>) future).tryFailure(e);
}
CompletableFuture<PubSubConnectionEntry> future = subscribeService.subscribe(codec, channelName, pubSubListener);
CompletableFuture<Integer> f = future.thenApply(res -> {
return System.identityHashCode(pubSubListener);
});
future.onComplete((res, e) -> {
if (e != null) {
result.tryFailure(e);
return;
}
result.trySuccess(System.identityHashCode(pubSubListener));
});
return result;
return new CompletableFutureWrapper<>(f);
}
@Override
@ -174,22 +163,24 @@ public class RedissonTopic implements RTopic {
@Override
public void removeListener(MessageListener<?> listener) {
RFuture<Void> future = removeListenerAsync(listener);
commandExecutor.syncSubscription(future);
commandExecutor.syncSubscription(future.toCompletableFuture());
}
@Override
public RFuture<Void> removeListenerAsync(MessageListener<?> listener) {
return subscribeService.removeListenerAsync(PubSubType.UNSUBSCRIBE, channelName, listener);
CompletableFuture<Void> f = subscribeService.removeListenerAsync(PubSubType.UNSUBSCRIBE, channelName, listener);
return new CompletableFutureWrapper<>(f);
}
@Override
public RFuture<Void> removeListenerAsync(Integer... listenerIds) {
return subscribeService.removeListenerAsync(PubSubType.UNSUBSCRIBE, channelName, listenerIds);
CompletableFuture<Void> f = subscribeService.removeListenerAsync(PubSubType.UNSUBSCRIBE, channelName, listenerIds);
return new CompletableFutureWrapper<>(f);
}
@Override
public void removeListener(Integer... listenerIds) {
commandExecutor.syncSubscription(removeListenerAsync(listenerIds));
commandExecutor.syncSubscription(removeListenerAsync(listenerIds).toCompletableFuture());
}
@Override

@ -214,7 +214,7 @@ public final class RedisClient {
if (future.isSuccess()) {
RedisConnection c = RedisConnection.getFrom(future.channel());
c.getConnectionPromise().onComplete((res, e) -> {
c.getConnectionPromise().whenComplete((res, e) -> {
bootstrap.config().group().execute(new Runnable() {
@Override
public void run() {
@ -271,7 +271,7 @@ public final class RedisClient {
if (future.isSuccess()) {
RedisPubSubConnection c = RedisPubSubConnection.getFrom(future.channel());
c.getConnectionPromise().onComplete((res, e) -> {
c.getConnectionPromise().whenComplete((res, e) -> {
pubSubBootstrap.config().group().execute(new Runnable() {
@Override
public void run() {

@ -26,16 +26,18 @@ import org.redisson.client.codec.Codec;
import org.redisson.client.handler.CommandsQueue;
import org.redisson.client.handler.CommandsQueuePubSub;
import org.redisson.client.protocol.*;
import org.redisson.misc.CompletableFutureWrapper;
import org.redisson.misc.LogHelper;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Deque;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
/**
@ -50,18 +52,18 @@ public class RedisConnection implements RedisCommands {
final RedisClient redisClient;
private volatile RPromise<Void> fastReconnect;
private volatile CompletableFuture<Void> fastReconnect;
private volatile boolean closed;
volatile Channel channel;
private RPromise<?> connectionPromise;
private CompletableFuture<?> connectionPromise;
private long lastUsageTime;
private Runnable connectedListener;
private Runnable disconnectedListener;
private final AtomicInteger usage = new AtomicInteger();
public <C> RedisConnection(RedisClient redisClient, Channel channel, RPromise<C> connectionPromise) {
public <C> RedisConnection(RedisClient redisClient, Channel channel, CompletableFuture<C> connectionPromise) {
this.redisClient = redisClient;
this.connectionPromise = connectionPromise;
@ -107,8 +109,8 @@ public class RedisConnection implements RedisCommands {
this.disconnectedListener = disconnectedListener;
}
public <C extends RedisConnection> RPromise<C> getConnectionPromise() {
return (RPromise<C>) connectionPromise;
public <C extends RedisConnection> CompletableFuture<C> getConnectionPromise() {
return (CompletableFuture<C>) connectionPromise;
}
public static <C extends RedisConnection> C getFrom(Channel channel) {
@ -179,26 +181,18 @@ public class RedisConnection implements RedisCommands {
return redisClient;
}
public <R> R await(RFuture<R> future) {
CountDownLatch l = new CountDownLatch(1);
future.onComplete((res, e) -> {
l.countDown();
});
public <R> R await(CompletableFuture<R> future) {
try {
if (!l.await(redisClient.getCommandTimeout(), TimeUnit.MILLISECONDS)) {
RPromise<R> promise = (RPromise<R>) future;
RedisTimeoutException ex = new RedisTimeoutException("Command execution timeout for " + redisClient.getAddr());
promise.tryFailure(ex);
throw ex;
}
if (!future.isSuccess()) {
if (future.cause() instanceof RedisException) {
throw (RedisException) future.cause();
}
throw new RedisException("Unexpected exception while processing command", future.cause());
return future.get(redisClient.getCommandTimeout(), TimeUnit.MILLISECONDS);
} catch (ExecutionException e) {
if (e.getCause() instanceof RedisException) {
throw (RedisException) e.getCause();
}
return future.getNow();
throw new RedisException("Unexpected exception while processing command", e.getCause());
} catch (TimeoutException e) {
RedisTimeoutException ex = new RedisTimeoutException("Command execution timeout for " + redisClient.getAddr());
future.completeExceptionally(ex);
throw ex;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
@ -218,7 +212,7 @@ public class RedisConnection implements RedisCommands {
}
public <T, R> R sync(Codec encoder, RedisCommand<T> command, Object... params) {
RPromise<R> promise = new RedissonPromise<R>();
CompletableFuture<R> promise = new CompletableFuture<>();
send(new CommandData<T, R>(promise, encoder, command, params));
return await(promise);
}
@ -236,7 +230,7 @@ public class RedisConnection implements RedisCommands {
}
public <T, R> RFuture<R> async(long timeout, Codec encoder, RedisCommand<T> command, Object... params) {
RPromise<R> promise = new RedissonPromise<R>();
CompletableFuture<R> promise = new CompletableFuture<>();
if (timeout == -1) {
timeout = redisClient.getCommandTimeout();
}
@ -249,28 +243,25 @@ public class RedisConnection implements RedisCommands {
Timeout scheduledFuture = redisClient.getTimer().newTimeout(t -> {
RedisTimeoutException ex = new RedisTimeoutException("Command execution timeout for command: "
+ LogHelper.toString(command, params) + ", Redis client: " + redisClient);
promise.tryFailure(ex);
promise.completeExceptionally(ex);
}, timeout, TimeUnit.MILLISECONDS);
promise.onComplete((res, e) -> {
promise.whenComplete((res, e) -> {
scheduledFuture.cancel();
});
ChannelFuture writeFuture = send(new CommandData<T, R>(promise, encoder, command, params));
writeFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
promise.tryFailure(future.cause());
}
ChannelFuture writeFuture = send(new CommandData<>(promise, encoder, command, params));
writeFuture.addListener((ChannelFutureListener) future -> {
if (!future.isSuccess()) {
promise.completeExceptionally(future.cause());
}
});
return promise;
return new CompletableFutureWrapper<>(promise);
}
public <T, R> CommandData<T, R> create(Codec encoder, RedisCommand<T> command, Object... params) {
RPromise<R> promise = new RedissonPromise<R>();
return new CommandData<T, R>(promise, encoder, command, params);
CompletableFuture<R> promise = new CompletableFuture<>();
return new CommandData<>(promise, encoder, command, params);
}
private void setClosed(boolean closed) {
@ -286,7 +277,7 @@ public class RedisConnection implements RedisCommands {
}
public void clearFastReconnect() {
fastReconnect.trySuccess(null);
fastReconnect.complete(null);
fastReconnect = null;
}
@ -304,8 +295,8 @@ public class RedisConnection implements RedisCommands {
}
}
public RFuture<Void> forceFastReconnectAsync() {
RedissonPromise<Void> promise = new RedissonPromise<Void>();
public CompletableFuture<Void> forceFastReconnectAsync() {
CompletableFuture<Void> promise = new CompletableFuture<Void>();
fastReconnect = promise;
close();
return promise;

@ -15,32 +15,21 @@
*/
package org.redisson.client;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;
import org.redisson.client.codec.Codec;
import org.redisson.client.protocol.CommandData;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.client.protocol.RedisCommands;
import org.redisson.client.protocol.decoder.MultiDecoder;
import org.redisson.client.protocol.pubsub.PubSubMessage;
import org.redisson.client.protocol.pubsub.PubSubMessageDecoder;
import org.redisson.client.protocol.pubsub.PubSubPatternMessage;
import org.redisson.client.protocol.pubsub.PubSubPatternMessageDecoder;
import org.redisson.client.protocol.pubsub.PubSubStatusMessage;
import org.redisson.client.protocol.pubsub.PubSubType;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import org.redisson.client.protocol.pubsub.*;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
*
@ -55,7 +44,7 @@ public class RedisPubSubConnection extends RedisConnection {
final Set<ChannelName> unsubscibedChannels = new HashSet<ChannelName>();
final Set<ChannelName> punsubscibedChannels = new HashSet<ChannelName>();
public RedisPubSubConnection(RedisClient redisClient, Channel channel, RPromise<RedisPubSubConnection> connectionPromise) {
public RedisPubSubConnection(RedisClient redisClient, Channel channel, CompletableFuture<RedisPubSubConnection> connectionPromise) {
super(redisClient, channel, connectionPromise);
}
@ -169,8 +158,8 @@ public class RedisPubSubConnection extends RedisConnection {
}
private <T, R> ChannelFuture async(MultiDecoder<Object> messageDecoder, RedisCommand<T> command, Object... params) {
RPromise<R> promise = new RedissonPromise<R>();
return channel.writeAndFlush(new CommandData<T, R>(promise, messageDecoder, null, command, params));
CompletableFuture<R> promise = new CompletableFuture<>();
return channel.writeAndFlush(new CommandData<>(promise, messageDecoder, null, command, params));
}
public Map<ChannelName, Codec> getChannels() {

@ -15,10 +15,9 @@
*/
package org.redisson.client;
import org.redisson.api.RFuture;
import org.redisson.client.protocol.pubsub.PubSubType;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import java.util.concurrent.CompletableFuture;
/**
*
@ -27,7 +26,7 @@ import org.redisson.misc.RedissonPromise;
*/
public class SubscribeListener extends BaseRedisPubSubListener {
private final RPromise<Void> promise = new RedissonPromise<>();
private final CompletableFuture<Void> promise = new CompletableFuture<>();
private final ChannelName name;
private final PubSubType type;
@ -40,12 +39,12 @@ public class SubscribeListener extends BaseRedisPubSubListener {
@Override
public boolean onStatus(PubSubType type, CharSequence channel) {
if (name.equals(channel) && this.type.equals(type)) {
promise.trySuccess(null);
promise.complete(null);
}
return true;
}
public RFuture<Void> getSuccessFuture() {
public CompletableFuture<Void> getSuccessFuture() {
return promise;
}

@ -15,23 +15,21 @@
*/
package org.redisson.client.handler;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.redisson.api.RFuture;
import org.redisson.client.RedisClient;
import org.redisson.client.RedisClientConfig;
import org.redisson.client.RedisConnection;
import org.redisson.client.RedisLoadingException;
import org.redisson.client.protocol.RedisCommands;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
@ -41,7 +39,7 @@ import io.netty.channel.ChannelInboundHandlerAdapter;
public abstract class BaseConnectionHandler<C extends RedisConnection> extends ChannelInboundHandlerAdapter {
final RedisClient redisClient;
final RPromise<C> connectionPromise = new RedissonPromise<C>();
final CompletableFuture<C> connectionPromise = new CompletableFuture<C>();
C connection;
public BaseConnectionHandler(RedisClient redisClient) {
@ -92,7 +90,7 @@ public abstract class BaseConnectionHandler<C extends RedisConnection> extends C
if (futures.isEmpty()) {
ctx.fireChannelActive();
connectionPromise.trySuccess(connection);
connectionPromise.complete(connection);
return;
}
@ -110,12 +108,12 @@ public abstract class BaseConnectionHandler<C extends RedisConnection> extends C
return;
}
connection.closeAsync();
connectionPromise.tryFailure(e);
connectionPromise.completeExceptionally(e);
return;
}
if (commandsCounter.decrementAndGet() == 0) {
ctx.fireChannelActive();
connectionPromise.trySuccess(connection);
connectionPromise.complete(connection);
}
});
}

@ -41,13 +41,13 @@ import org.redisson.client.codec.StringCodec;
import org.redisson.client.protocol.*;
import org.redisson.client.protocol.decoder.MultiDecoder;
import org.redisson.misc.LogHelper;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedisURI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
/**
* Redis protocol command decoder
@ -211,7 +211,7 @@ public class CommandDecoder extends ReplayingDecoder<State> {
} catch (Exception e) {
in.readerIndex(endIndex);
sendNext(channel);
commands.getPromise().tryFailure(e);
commands.getPromise().completeExceptionally(e);
throw e;
}
} else {
@ -272,8 +272,8 @@ public class CommandDecoder extends ReplayingDecoder<State> {
if (commandData != null
&& RedisCommands.EXEC.getName().equals(commandData.getCommand().getName())
&& commandData.getPromise().isSuccess()) {
List<Object> objects = (List<Object>) commandData.getPromise().getNow();
&& (commandData.getPromise().isDone() && !commandData.getPromise().isCompletedExceptionally())) {
List<Object> objects = (List<Object>) commandData.getPromise().getNow(null);
Iterator<Object> iter = objects.iterator();
boolean multiFound = false;
for (CommandData<?, ?> command : commandBatch.getCommands()) {
@ -311,11 +311,11 @@ public class CommandDecoder extends ReplayingDecoder<State> {
}
if (commandBatch.isSkipResult() || i == commandBatch.getCommands().size()) {
RPromise<Void> promise = commandBatch.getPromise();
CompletableFuture<Void> promise = commandBatch.getPromise();
if (error != null) {
promise.tryFailure(error);
promise.completeExceptionally(error);
} else {
promise.trySuccess(null);
promise.complete(null);
}
sendNext(channel);
@ -418,7 +418,7 @@ public class CommandDecoder extends ReplayingDecoder<State> {
}
CommandData<Object, Object> commandData = (CommandData<Object, Object>) commandsData.get(i+suffix);
decode(in, commandData, respParts, channel, skipConvertor, commandsData);
if (commandData.getPromise().isDone() && !commandData.getPromise().isSuccess()) {
if (commandData.getPromise().isDone() && commandData.getPromise().isCompletedExceptionally()) {
data.tryFailure(commandData.cause());
}
}
@ -457,7 +457,7 @@ public class CommandDecoder extends ReplayingDecoder<State> {
protected void completeResponse(CommandData<Object, Object> data, Object result) {
if (data != null) {
data.getPromise().trySuccess(result);
data.getPromise().complete(result);
}
}

@ -135,7 +135,7 @@ public class ConnectionWatchdog extends ChannelInboundHandlerAdapter {
connection.getRedisClient().getAddr(), channel.localAddress(), channel.remoteAddress());
} else {
RedisConnection c = RedisConnection.getFrom(channel);
c.getConnectionPromise().onComplete((res, e) -> {
c.getConnectionPromise().whenComplete((res, e) -> {
if (e == null) {
if (connection.getRedisClient().isShutdown()
|| connection.isClosed()) {

@ -47,7 +47,7 @@ public class PingConnectionHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
RedisConnection connection = RedisConnection.getFrom(ctx.channel());
connection.getConnectionPromise().onComplete((res, e) -> {
connection.getConnectionPromise().whenComplete((res, e) -> {
if (e == null) {
sendPing(ctx);
}

@ -198,7 +198,7 @@ public class RedisChannelInitializer extends ChannelInitializer<Channel> {
} else {
RedisConnection connection = RedisConnection.getFrom(ctx.channel());
connection.closeAsync();
connection.getConnectionPromise().tryFailure(e.cause());
connection.getConnectionPromise().completeExceptionally(e.cause());
}
}

@ -15,13 +15,12 @@
*/
package org.redisson.client.protocol;
import java.util.concurrent.atomic.AtomicReference;
import org.redisson.client.RedisRedirectException;
import org.redisson.client.codec.Codec;
import org.redisson.client.codec.StringCodec;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
/**
*
@ -36,10 +35,10 @@ public class BatchCommandData<T, R> extends CommandData<T, R> implements Compara
private final AtomicReference<RedisRedirectException> redirectError = new AtomicReference<RedisRedirectException>();
public BatchCommandData(RedisCommand<T> command, Object[] params, int index) {
this(new RedissonPromise<R>(), StringCodec.INSTANCE, command, params, index);
this(new CompletableFuture<>(), StringCodec.INSTANCE, command, params, index);
}
public BatchCommandData(RPromise<R> promise, Codec codec, RedisCommand<T> command, Object[] params, int index) {
public BatchCommandData(CompletableFuture<R> promise, Codec codec, RedisCommand<T> command, Object[] params, int index) {
super(promise, codec, command, params);
this.index = index;
}

@ -15,13 +15,14 @@
*/
package org.redisson.client.protocol;
import java.util.Collections;
import java.util.List;
import org.redisson.client.codec.Codec;
import org.redisson.client.protocol.decoder.MultiDecoder;
import org.redisson.misc.LogHelper;
import org.redisson.misc.RPromise;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
/**
*
@ -32,17 +33,17 @@ import org.redisson.misc.RPromise;
*/
public class CommandData<T, R> implements QueueCommand {
final RPromise<R> promise;
final CompletableFuture<R> promise;
final RedisCommand<T> command;
final Object[] params;
final Codec codec;
final MultiDecoder<Object> messageDecoder;
public CommandData(RPromise<R> promise, Codec codec, RedisCommand<T> command, Object[] params) {
public CommandData(CompletableFuture<R> promise, Codec codec, RedisCommand<T> command, Object[] params) {
this(promise, null, codec, command, params);
}
public CommandData(RPromise<R> promise, MultiDecoder<Object> messageDecoder, Codec codec, RedisCommand<T> command, Object[] params) {
public CommandData(CompletableFuture<R> promise, MultiDecoder<Object> messageDecoder, Codec codec, RedisCommand<T> command, Object[] params) {
this.promise = promise;
this.command = command;
this.params = params;
@ -62,20 +63,25 @@ public class CommandData<T, R> implements QueueCommand {
return messageDecoder;
}
public RPromise<R> getPromise() {
public CompletableFuture<R> getPromise() {
return promise;
}
public Throwable cause() {
return promise.cause();
try {
promise.getNow(null);
return null;
} catch (CompletionException e) {
return e.getCause();
}
}
public boolean isSuccess() {
return promise.isSuccess();
return promise.isDone() && !promise.isCompletedExceptionally();
}
public boolean tryFailure(Throwable cause) {
return promise.tryFailure(cause);
return promise.completeExceptionally(cause);
}
public Codec getCodec() {

@ -17,8 +17,7 @@ package org.redisson.client.protocol;
import java.util.ArrayList;
import java.util.List;
import org.redisson.misc.RPromise;
import java.util.concurrent.CompletableFuture;
/**
*
@ -29,21 +28,21 @@ public class CommandsData implements QueueCommand {
private final List<CommandData<?, ?>> commands;
private final List<CommandData<?, ?>> attachedCommands;
private final RPromise<Void> promise;
private final CompletableFuture<Void> promise;
private final boolean skipResult;
private final boolean atomic;
private final boolean queued;
private final boolean syncSlaves;
public CommandsData(RPromise<Void> promise, List<CommandData<?, ?>> commands, boolean queued, boolean syncSlaves) {
public CommandsData(CompletableFuture<Void> promise, List<CommandData<?, ?>> commands, boolean queued, boolean syncSlaves) {
this(promise, commands, null, false, false, queued, syncSlaves);
}
public CommandsData(RPromise<Void> promise, List<CommandData<?, ?>> commands, boolean skipResult, boolean atomic, boolean queued, boolean syncSlaves) {
public CommandsData(CompletableFuture<Void> promise, List<CommandData<?, ?>> commands, boolean skipResult, boolean atomic, boolean queued, boolean syncSlaves) {
this(promise, commands, null, skipResult, atomic, queued, syncSlaves);
}
public CommandsData(RPromise<Void> promise, List<CommandData<?, ?>> commands, List<CommandData<?, ?>> attachedCommands,
public CommandsData(CompletableFuture<Void> promise, List<CommandData<?, ?>> commands, List<CommandData<?, ?>> attachedCommands,
boolean skipResult, boolean atomic, boolean queued, boolean syncSlaves) {
super();
this.promise = promise;
@ -59,7 +58,7 @@ public class CommandsData implements QueueCommand {
return syncSlaves;
}
public RPromise<Void> getPromise() {
public CompletableFuture<Void> getPromise() {
return promise;
}
@ -96,7 +95,7 @@ public class CommandsData implements QueueCommand {
@Override
public boolean tryFailure(Throwable cause) {
return promise.tryFailure(cause);
return promise.completeExceptionally(cause);
}
@Override

@ -15,10 +15,6 @@
*/
package org.redisson.command;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.redisson.api.BatchOptions;
import org.redisson.client.codec.Codec;
import org.redisson.client.protocol.BatchCommandData;
@ -28,7 +24,11 @@ import org.redisson.connection.ConnectionManager;
import org.redisson.connection.MasterSlaveEntry;
import org.redisson.connection.NodeSource;
import org.redisson.liveobject.core.RedissonObjectBuilder;
import org.redisson.misc.RPromise;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
@ -47,7 +47,7 @@ public class BaseRedisBatchExecutor<V, R> extends RedisExecutor<V, R> {
@SuppressWarnings("ParameterNumber")
public BaseRedisBatchExecutor(boolean readOnlyMode, NodeSource source, Codec codec, RedisCommand<V> command,
Object[] params, RPromise<R> mainPromise, boolean ignoreRedirect,
Object[] params, CompletableFuture<R> mainPromise, boolean ignoreRedirect,
ConnectionManager connectionManager, RedissonObjectBuilder objectBuilder,
ConcurrentMap<MasterSlaveEntry, Entry> commands,
BatchOptions options, AtomicInteger index, AtomicBoolean executed, RedissonObjectBuilder.ReferenceType referenceType,

@ -15,28 +15,22 @@
*/
package org.redisson.command;
import java.util.concurrent.atomic.AtomicBoolean;
import org.redisson.api.RFuture;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import java.util.concurrent.CompletableFuture;
/**
*
* @author Nikita Koksharov
*
*/
public class BatchPromise<T> extends RedissonPromise<T> {
public class BatchPromise<T> extends CompletableFuture<T> {
private final AtomicBoolean executed;
private final RFuture<Void> sentPromise = new RedissonPromise<Void>();
private final CompletableFuture<Void> sentPromise = new CompletableFuture<>();
public BatchPromise(AtomicBoolean executed) {
public BatchPromise() {
super();
this.executed = executed;
}
public RFuture<Void> getSentPromise() {
public CompletableFuture<Void> getSentPromise() {
return sentPromise;
}
@ -45,20 +39,4 @@ public class BatchPromise<T> extends RedissonPromise<T> {
return false;
}
@Override
public RPromise<T> sync() throws InterruptedException {
if (executed.get()) {
return super.sync();
}
return (RPromise<T>) sentPromise.sync();
}
@Override
public RPromise<T> syncUninterruptibly() {
if (executed.get()) {
return super.syncUninterruptibly();
}
return (RPromise<T>) sentPromise.syncUninterruptibly();
}
}

@ -26,10 +26,10 @@ import org.redisson.connection.ConnectionManager;
import org.redisson.connection.MasterSlaveEntry;
import org.redisson.connection.NodeSource;
import org.redisson.liveobject.core.RedissonObjectBuilder;
import org.redisson.misc.RPromise;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
/**
@ -45,9 +45,13 @@ public interface CommandAsyncExecutor {
RedisException convertException(ExecutionException e);
void syncSubscription(RFuture<?> future);
void syncSubscription(CompletableFuture<?> future);
void syncSubscriptionInterrupted(RFuture<?> future) throws InterruptedException;
void syncSubscriptionInterrupted(CompletableFuture<?> future) throws InterruptedException;
<V> void transfer(CompletableFuture<V> future1, CompletableFuture<V> future2);
<V> V getNow(CompletableFuture<V> future);
<V> V get(RFuture<V> future);
@ -111,9 +115,8 @@ public interface CommandAsyncExecutor {
<T, R> RFuture<R> readRandomAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> command, Object... params);
<V, R> void async(boolean readOnlyMode, NodeSource source, Codec codec,
RedisCommand<V> command, Object[] params, RPromise<R> mainPromise,
boolean ignoreRedirect, boolean noRetry);
<V, R> RFuture<R> async(boolean readOnlyMode, NodeSource source, Codec codec,
RedisCommand<V> command, Object[] params, boolean ignoreRedirect, boolean noRetry);
<V> RFuture<V> pollFromAnyAsync(String name, Codec codec, RedisCommand<Object> command, long secondsTimeout, String... queueNames);

@ -36,6 +36,7 @@ import org.redisson.connection.ConnectionManager;
import org.redisson.connection.MasterSlaveEntry;
import org.redisson.connection.NodeSource;
import org.redisson.liveobject.core.RedissonObjectBuilder;
import org.redisson.misc.CompletableFutureWrapper;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import org.slf4j.Logger;
@ -81,11 +82,11 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
@Override
public void syncSubscription(RFuture<?> future) {
public void syncSubscription(CompletableFuture<?> future) {
MasterSlaveServersConfig config = connectionManager.getConfig();
int timeout = config.getTimeout() + config.getRetryInterval() * config.getRetryAttempts();
try {
future.toCompletableFuture().get(timeout, TimeUnit.MILLISECONDS);
future.get(timeout, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (CancellationException e) {
@ -93,25 +94,46 @@ public class CommandAsyncService implements CommandAsyncExecutor {
} catch (ExecutionException e) {
throw (RuntimeException) e.getCause();
} catch (TimeoutException e) {
((RPromise<?>) future).tryFailure(new RedisTimeoutException("Subscribe timeout: (" + timeout + "ms). Increase 'subscriptionsPerConnection' and/or 'subscriptionConnectionPoolSize' parameters."));
future.completeExceptionally(new RedisTimeoutException("Subscribe timeout: (" + timeout + "ms). Increase 'subscriptionsPerConnection' and/or 'subscriptionConnectionPoolSize' parameters."));
}
}
@Override
public void syncSubscriptionInterrupted(RFuture<?> future) throws InterruptedException {
public void syncSubscriptionInterrupted(CompletableFuture<?> future) throws InterruptedException {
MasterSlaveServersConfig config = connectionManager.getConfig();
int timeout = config.getTimeout() + config.getRetryInterval() * config.getRetryAttempts();
try {
future.toCompletableFuture().get(timeout, TimeUnit.MILLISECONDS);
future.get(timeout, TimeUnit.MILLISECONDS);
} catch (CancellationException e) {
// skip
} catch (ExecutionException e) {
throw (RuntimeException) e.getCause();
} catch (TimeoutException e) {
((RPromise<?>) future).tryFailure(new RedisTimeoutException("Subscribe timeout: (" + timeout + "ms). Increase 'subscriptionsPerConnection' and/or 'subscriptionConnectionPoolSize' parameters."));
future.completeExceptionally(new RedisTimeoutException("Subscribe timeout: (" + timeout + "ms). Increase 'subscriptionsPerConnection' and/or 'subscriptionConnectionPoolSize' parameters."));
}
}
@Override
public <V> V getNow(CompletableFuture<V> future) {
try {
return future.getNow(null);
} catch (Exception e) {
return null;
}
}
@Override
public <V> void transfer(CompletableFuture<V> future1, CompletableFuture<V> future2) {
future1.whenComplete((res, e) -> {
if (e != null) {
future2.completeExceptionally(e);
return;
}
future2.complete(res);
});
}
@Override
public <V> V get(RFuture<V> future) {
if (Thread.currentThread().getName().startsWith("redisson-netty")) {
@ -134,44 +156,36 @@ public class CommandAsyncService implements CommandAsyncExecutor {
try {
return future.toCompletableFuture().get();
} catch (InterruptedException e) {
((RPromise) future).tryFailure(e);
future.toCompletableFuture().completeExceptionally(e);
throw e;
} catch (ExecutionException e) {
throw convertException(e);
}
}
protected <R> RPromise<R> createPromise() {
return new RedissonPromise<R>();
protected <R> CompletableFuture<R> createPromise() {
return new CompletableFuture<R>();
}
@Override
public <T, R> RFuture<R> readAsync(RedisClient client, MasterSlaveEntry entry, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
async(true, new NodeSource(entry, client), codec, command, params, mainPromise, false, false);
return mainPromise;
return async(true, new NodeSource(entry, client), codec, command, params, false, false);
}
@Override
public <T, R> RFuture<R> readAsync(RedisClient client, String name, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
int slot = connectionManager.calcSlot(name);
async(true, new NodeSource(slot, client), codec, command, params, mainPromise, false, false);
return mainPromise;
return async(true, new NodeSource(slot, client), codec, command, params, false, false);
}
public <T, R> RFuture<R> readAsync(RedisClient client, byte[] key, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
int slot = connectionManager.calcSlot(key);
async(true, new NodeSource(slot, client), codec, command, params, mainPromise, false, false);
return mainPromise;
return async(true, new NodeSource(slot, client), codec, command, params, false, false);
}
@Override
public <T, R> RFuture<R> readAsync(RedisClient client, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
async(true, new NodeSource(client), codec, command, params, mainPromise, false, false);
return mainPromise;
return async(true, new NodeSource(client), codec, command, params, false, false);
}
@Override
@ -188,14 +202,14 @@ public class CommandAsyncService implements CommandAsyncExecutor {
@Override
public <T, R> RFuture<Collection<R>> readAllAsync(Collection<R> results, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<Collection<R>> mainPromise = createPromise();
CompletableFuture<Collection<R>> mainPromise = createPromise();
Collection<MasterSlaveEntry> nodes = connectionManager.getEntrySet();
AtomicInteger counter = new AtomicInteger(nodes.size());
BiConsumer<Object, Throwable> listener = new BiConsumer<Object, Throwable>() {
@Override
public void accept(Object result, Throwable u) {
if (u != null && !(u instanceof RedisRedirectException)) {
mainPromise.tryFailure(u);
mainPromise.completeExceptionally(u);
return;
}
@ -211,57 +225,54 @@ public class CommandAsyncService implements CommandAsyncExecutor {
if (counter.decrementAndGet() == 0
&& !mainPromise.isDone()) {
mainPromise.trySuccess(results);
mainPromise.complete(results);
}
}
};
for (MasterSlaveEntry entry : nodes) {
RPromise<R> promise = new RedissonPromise<R>();
promise.onComplete(listener);
async(true, new NodeSource(entry), codec, command, params, promise, true, false);
RFuture<Object> f = async(true, new NodeSource(entry), codec, command, params, true, false);
f.whenComplete(listener);
}
return mainPromise;
return new CompletableFutureWrapper<>(mainPromise);
}
@Override
public <T, R> RFuture<R> readRandomAsync(Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
CompletableFuture<R> mainPromise = createPromise();
List<MasterSlaveEntry> nodes = new ArrayList<MasterSlaveEntry>(connectionManager.getEntrySet());
Collections.shuffle(nodes);
retryReadRandomAsync(codec, command, mainPromise, nodes, params);
return mainPromise;
return new CompletableFutureWrapper<>(mainPromise);
}
@Override
public <T, R> RFuture<R> readRandomAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
CompletableFuture<R> mainPromise = createPromise();
retryReadRandomAsync(codec, command, mainPromise, Collections.singletonList(entry), params);
return mainPromise;
return new CompletableFutureWrapper<>(mainPromise);
}
private <R, T> void retryReadRandomAsync(Codec codec, RedisCommand<T> command, RPromise<R> mainPromise,
private <R, T> void retryReadRandomAsync(Codec codec, RedisCommand<T> command, CompletableFuture<R> mainPromise,
List<MasterSlaveEntry> nodes, Object... params) {
RPromise<R> attemptPromise = new RedissonPromise<R>();
attemptPromise.onComplete((res, e) -> {
MasterSlaveEntry entry = nodes.remove(0);
RFuture<R> attemptPromise = async(true, new NodeSource(entry), codec, command, params, false, false);
attemptPromise.whenComplete((res, e) -> {
if (e == null) {
if (res == null) {
if (nodes.isEmpty()) {
mainPromise.trySuccess(null);
mainPromise.complete(null);
} else {
retryReadRandomAsync(codec, command, mainPromise, nodes, params);
}
} else {
mainPromise.trySuccess(res);
mainPromise.complete(res);
}
} else {
mainPromise.tryFailure(e);
mainPromise.completeExceptionally(e);
}
});
MasterSlaveEntry entry = nodes.remove(0);
async(true, new NodeSource(entry), codec, command, params, attemptPromise, false, false);
}
@Override
@ -314,9 +325,8 @@ public class CommandAsyncService implements CommandAsyncExecutor {
};
for (MasterSlaveEntry entry : nodes) {
RPromise<T> promise = new RedissonPromise<T>();
promise.onComplete(listener);
async(readOnlyMode, new NodeSource(entry), codec, command, params, promise, true, false);
RFuture<T> promise = async(readOnlyMode, new NodeSource(entry), codec, command, params, true, false);
promise.whenComplete(listener);
}
return mainPromise;
}
@ -340,24 +350,18 @@ public class CommandAsyncService implements CommandAsyncExecutor {
@Override
public <T, R> RFuture<R> readAsync(String key, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
NodeSource source = getNodeSource(key);
async(true, source, codec, command, params, mainPromise, false, false);
return mainPromise;
return async(true, source, codec, command, params, false, false);
}
@Override
public <T, R> RFuture<R> readAsync(byte[] key, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
NodeSource source = getNodeSource(key);
async(true, source, codec, command, params, mainPromise, false, false);
return mainPromise;
return async(true, source, codec, command, params, false, false);
}
public <T, R> RFuture<R> readAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
async(true, new NodeSource(entry), codec, command, params, mainPromise, false, false);
return mainPromise;
return async(true, new NodeSource(entry), codec, command, params, false, false);
}
@Override
@ -368,9 +372,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
@Override
public <T, R> RFuture<R> writeAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
async(false, new NodeSource(entry), codec, command, params, mainPromise, false, false);
return mainPromise;
return async(false, new NodeSource(entry), codec, command, params, false, false);
}
@Override
@ -442,9 +444,8 @@ public class CommandAsyncService implements CommandAsyncExecutor {
args.addAll(keys);
args.addAll(Arrays.asList(params));
for (MasterSlaveEntry entry : entries) {
RPromise<T> promise = new RedissonPromise<T>();
promise.onComplete(listener);
async(readOnlyMode, new NodeSource(entry), connectionManager.getCodec(), command, args.toArray(), promise, true, false);
RFuture<T> promise = async(readOnlyMode, new NodeSource(entry), connectionManager.getCodec(), command, args.toArray(), true, false);
promise.whenComplete(listener);
}
return mainPromise;
}
@ -498,11 +499,11 @@ public class CommandAsyncService implements CommandAsyncExecutor {
private <T, R> RFuture<R> evalAsync(NodeSource nodeSource, boolean readOnlyMode, Codec codec, RedisCommand<T> evalCommandType,
String script, List<Object> keys, boolean noRetry, Object... params) {
if (isEvalCacheActive() && evalCommandType.getName().equals("EVAL")) {
RPromise<R> mainPromise = new RedissonPromise<R>();
CompletableFuture<R> mainPromise = new CompletableFuture<>();
Object[] pps = copy(params);
RPromise<R> promise = new RedissonPromise<R>();
CompletableFuture<R> promise = new CompletableFuture<>();
String sha1 = calcSHA(script);
RedisCommand cmd = new RedisCommand(evalCommandType, "EVALSHA");
List<Object> args = new ArrayList<Object>(2 + keys.size() + params.length);
@ -516,14 +517,14 @@ public class CommandAsyncService implements CommandAsyncExecutor {
connectionManager, objectBuilder, referenceType, noRetry);
executor.execute();
promise.onComplete((res, e) -> {
promise.whenComplete((res, e) -> {
if (e != null) {
if (e.getMessage().startsWith("NOSCRIPT")) {
RFuture<String> loadFuture = loadScript(executor.getRedisClient(), script);
loadFuture.onComplete((r, ex) -> {
if (ex != null) {
free(pps);
mainPromise.tryFailure(ex);
mainPromise.completeExceptionally(ex);
return;
}
@ -539,28 +540,33 @@ public class CommandAsyncService implements CommandAsyncExecutor {
ns = new NodeSource(nodeSource, executor.getRedisClient());
}
async(readOnlyMode, ns, codec, command, newargs.toArray(), mainPromise, false, noRetry);
RFuture<R> future = async(readOnlyMode, ns, codec, command, newargs.toArray(), false, noRetry);
future.whenComplete((re, exс) -> {
if (exс != null) {
mainPromise.completeExceptionally(exс);
} else {
mainPromise.complete(re);
}
});
});
} else {
free(pps);
mainPromise.tryFailure(e);
mainPromise.completeExceptionally(e);
}
return;
}
free(pps);
mainPromise.trySuccess(res);
mainPromise.complete(res);
});
return mainPromise;
return new CompletableFutureWrapper<>(mainPromise);
}
RPromise<R> mainPromise = createPromise();
List<Object> args = new ArrayList<Object>(2 + keys.size() + params.length);
args.add(script);
args.add(keys.size());
args.addAll(keys);
args.addAll(Arrays.asList(params));
async(readOnlyMode, nodeSource, codec, evalCommandType, args.toArray(), mainPromise, false, noRetry);
return mainPromise;
return async(readOnlyMode, nodeSource, codec, evalCommandType, args.toArray(), false, noRetry);
}
@Override
@ -570,25 +576,22 @@ public class CommandAsyncService implements CommandAsyncExecutor {
@Override
public <T, R> RFuture<R> writeAsync(String key, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
NodeSource source = getNodeSource(key);
async(false, source, codec, command, params, mainPromise, false, false);
return mainPromise;
return async(false, source, codec, command, params, false, false);
}
public <T, R> RFuture<R> writeAsync(byte[] key, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = createPromise();
NodeSource source = getNodeSource(key);
async(false, source, codec, command, params, mainPromise, false, false);
return mainPromise;
return async(false, source, codec, command, params, false, false);
}
public <V, R> void async(boolean readOnlyMode, NodeSource source, Codec codec,
RedisCommand<V> command, Object[] params, RPromise<R> mainPromise,
boolean ignoreRedirect, boolean noRetry) {
public <V, R> RFuture<R> async(boolean readOnlyMode, NodeSource source, Codec codec,
RedisCommand<V> command, Object[] params, boolean ignoreRedirect, boolean noRetry) {
CompletableFuture<R> mainPromise = createPromise();
RedisExecutor<V, R> executor = new RedisExecutor<>(readOnlyMode, source, codec, command, params, mainPromise,
ignoreRedirect, connectionManager, objectBuilder, referenceType, noRetry);
executor.execute();
return new CompletableFutureWrapper<>(mainPromise);
}
private void free(Object[] params) {

@ -34,6 +34,7 @@ import org.redisson.connection.MasterSlaveEntry;
import org.redisson.connection.NodeSource;
import org.redisson.liveobject.core.RedissonObjectBuilder;
import org.redisson.misc.AsyncCountDownLatch;
import org.redisson.misc.CompletableFutureWrapper;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
@ -53,14 +54,14 @@ public class CommandBatchService extends CommandAsyncService {
public static class ConnectionEntry {
boolean firstCommand = true;
RFuture<RedisConnection> connectionFuture;
CompletableFuture<RedisConnection> connectionFuture;
Runnable cancelCallback;
public RFuture<RedisConnection> getConnectionFuture() {
public CompletableFuture<RedisConnection> getConnectionFuture() {
return connectionFuture;
}
public void setConnectionFuture(RFuture<RedisConnection> connectionFuture) {
public void setConnectionFuture(CompletableFuture<RedisConnection> connectionFuture) {
this.connectionFuture = connectionFuture;
}
@ -151,8 +152,9 @@ public class CommandBatchService extends CommandAsyncService {
}
@Override
public <V, R> void async(boolean readOnlyMode, NodeSource nodeSource,
Codec codec, RedisCommand<V> command, Object[] params, RPromise<R> mainPromise, boolean ignoreRedirect, boolean noRetry) {
public <V, R> RFuture<R> async(boolean readOnlyMode, NodeSource nodeSource,
Codec codec, RedisCommand<V> command, Object[] params, boolean ignoreRedirect, boolean noRetry) {
CompletableFuture<R> mainPromise = createPromise();
if (isRedisBasedQueue()) {
boolean isReadOnly = options.getExecutionMode() == ExecutionMode.REDIS_READ_ATOMIC;
RedisExecutor<V, R> executor = new RedisQueuedBatchExecutor<>(isReadOnly, nodeSource, codec, command, params, mainPromise,
@ -163,16 +165,16 @@ public class CommandBatchService extends CommandAsyncService {
false, connectionManager, objectBuilder, commands, options, index, executed, referenceType, noRetry);
executor.execute();
}
return new CompletableFutureWrapper<>(mainPromise);
}
@Override
public <R> RPromise<R> createPromise() {
public <R> CompletableFuture<R> createPromise() {
if (isRedisBasedQueue()) {
return new BatchPromise<>(executed);
return new BatchPromise<>();
}
return new RedissonPromise<>();
return new CompletableFuture<>();
}
public void discard() {
@ -260,10 +262,10 @@ public class CommandBatchService extends CommandAsyncService {
}
RPromise<BatchResult<?>> promise = new RedissonPromise<>();
RPromise<Void> voidPromise = new RedissonPromise<Void>();
CompletableFuture<Void> voidPromise = new CompletableFuture<>();
if (this.options.isSkipResult()
&& this.options.getSyncSlaves() == 0) {
voidPromise.onComplete((res, ex) -> {
voidPromise.whenComplete((res, ex) -> {
executed.set(true);
if (ex != null) {
@ -283,7 +285,7 @@ public class CommandBatchService extends CommandAsyncService {
promise.trySuccess(new BatchResult<>(Collections.emptyList(), 0));
});
} else {
voidPromise.onComplete((res, ex) -> {
voidPromise.whenComplete((res, ex) -> {
executed.set(true);
if (ex != null) {
for (Entry e : commands.values()) {
@ -306,7 +308,7 @@ public class CommandBatchService extends CommandAsyncService {
int syncedSlaves = 0;
for (BatchCommandData<?, ?> commandEntry : entries) {
if (isWaitCommand(commandEntry)) {
syncedSlaves = (Integer) commandEntry.getPromise().getNow();
syncedSlaves = (Integer) commandEntry.getPromise().getNow(null);
} else if (!commandEntry.getCommand().getName().equals(RedisCommands.MULTI.getName())
&& !commandEntry.getCommand().getName().equals(RedisCommands.EXEC.getName())
&& !this.options.isSkipResult()) {
@ -315,7 +317,7 @@ public class CommandBatchService extends CommandAsyncService {
continue;
}
Object entryResult = commandEntry.getPromise().getNow();
Object entryResult = commandEntry.getPromise().getNow(null);
try {
if (objectBuilder != null) {
entryResult = objectBuilder.tryHandleReference(entryResult, referenceType);
@ -356,6 +358,17 @@ public class CommandBatchService extends CommandAsyncService {
return promise;
}
protected Throwable cause(CompletableFuture<?> future) {
try {
future.getNow(null);
return null;
} catch (CompletionException ex2) {
return ex2.getCause();
} catch (CancellationException ex1) {
return ex1;
}
}
private <R> RFuture<R> executeRedisBasedQueue() {
int permits = 0;
for (Entry entry : commands.values()) {
@ -393,8 +406,9 @@ public class CommandBatchService extends CommandAsyncService {
for (Entry entry : commands.values()) {
for (BatchCommandData<?, ?> command : entry.getCommands()) {
if (command.getPromise().isDone() && !command.getPromise().isSuccess()) {
resultPromise.tryFailure(command.getPromise().cause());
if (command.getPromise().isDone() && command.getPromise().isCompletedExceptionally()) {
resultPromise.tryFailure(cause(command.getPromise()));
break;
}
}
@ -407,10 +421,8 @@ public class CommandBatchService extends CommandAsyncService {
Map<MasterSlaveEntry, List<Object>> result = new ConcurrentHashMap<>();
List<CompletableFuture<Void>> futures = new ArrayList<>(commands.size());
for (Map.Entry<MasterSlaveEntry, Entry> entry : commands.entrySet()) {
RPromise<List<Object>> execPromise = new RedissonPromise<>();
async(entry.getValue().isReadOnlyMode(), new NodeSource(entry.getKey()), connectionManager.getCodec(), RedisCommands.EXEC,
new Object[] {}, execPromise, false, false);
RFuture<List<Object>> execPromise = async(entry.getValue().isReadOnlyMode(), new NodeSource(entry.getKey()),
connectionManager.getCodec(), RedisCommands.EXEC, new Object[] {}, false, false);
CompletionStage<Void> f = execPromise.thenCompose(r -> {
BatchCommandData<?, Integer> lastCommand = (BatchCommandData<?, Integer>) entry.getValue().getCommands().peekLast();
@ -441,12 +453,12 @@ public class CommandBatchService extends CommandAsyncService {
break;
}
RPromise<Object> promise = (RPromise<Object>) data.getPromise();
CompletableFuture<Object> promise = (CompletableFuture<Object>) data.getPromise();
if (resultIter.hasNext()) {
promise.trySuccess(resultIter.next());
promise.complete(resultIter.next());
} else {
// fix for https://github.com/redisson/redisson/issues/2212
promise.trySuccess(null);
promise.complete(null);
}
}
}
@ -460,17 +472,17 @@ public class CommandBatchService extends CommandAsyncService {
int syncedSlaves = 0;
for (BatchCommandData<?, ?> commandEntry : entries) {
if (isWaitCommand(commandEntry)) {
syncedSlaves += (Integer) commandEntry.getPromise().getNow();
syncedSlaves += (Integer) commandEntry.getPromise().getNow(null);
} else if (!commandEntry.getCommand().getName().equals(RedisCommands.MULTI.getName())
&& !commandEntry.getCommand().getName().equals(RedisCommands.EXEC.getName())) {
Object entryResult = commandEntry.getPromise().getNow();
Object entryResult = commandEntry.getPromise().getNow(null);
if (objectBuilder != null) {
entryResult = objectBuilder.tryHandleReference(entryResult, referenceType);
}
responses.add(entryResult);
}
}
BatchResult<Object> r = new BatchResult<Object>(responses, syncedSlaves);
BatchResult<Object> r = new BatchResult<>(responses, syncedSlaves);
resultPromise.trySuccess((R) r);
} catch (Exception e) {
resultPromise.tryFailure(e);
@ -490,13 +502,13 @@ public class CommandBatchService extends CommandAsyncService {
return c.getCommand().getName().equals(RedisCommands.WAIT.getName());
}
protected void handle(RPromise<Void> mainPromise, AtomicInteger slots, RFuture<?> future) {
protected void handle(CompletableFuture<Void> mainPromise, AtomicInteger slots, RFuture<?> future) {
if (future.isSuccess()) {
if (slots.decrementAndGet() == 0) {
mainPromise.trySuccess(null);
mainPromise.complete(null);
}
} else {
mainPromise.tryFailure(future.cause());
mainPromise.completeExceptionally(future.cause());
}
}

@ -15,10 +15,6 @@
*/
package org.redisson.command;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.redisson.api.BatchOptions;
import org.redisson.client.codec.Codec;
import org.redisson.client.protocol.RedisCommand;
@ -27,7 +23,11 @@ import org.redisson.connection.ConnectionManager;
import org.redisson.connection.MasterSlaveEntry;
import org.redisson.connection.NodeSource;
import org.redisson.liveobject.core.RedissonObjectBuilder;
import org.redisson.misc.RPromise;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
@ -40,7 +40,7 @@ public class RedisBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R> {
@SuppressWarnings("ParameterNumber")
public RedisBatchExecutor(boolean readOnlyMode, NodeSource source, Codec codec, RedisCommand<V> command,
Object[] params, RPromise<R> mainPromise, boolean ignoreRedirect, ConnectionManager connectionManager,
Object[] params, CompletableFuture<R> mainPromise, boolean ignoreRedirect, ConnectionManager connectionManager,
RedissonObjectBuilder objectBuilder, ConcurrentMap<MasterSlaveEntry, Entry> commands,
BatchOptions options, AtomicInteger index,
AtomicBoolean executed, RedissonObjectBuilder.ReferenceType referenceType, boolean noRetry) {

@ -20,7 +20,6 @@ import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelPromise;
import org.redisson.api.BatchOptions;
import org.redisson.api.BatchOptions.ExecutionMode;
import org.redisson.api.RFuture;
import org.redisson.client.RedisConnection;
import org.redisson.client.codec.StringCodec;
import org.redisson.client.protocol.CommandData;
@ -31,13 +30,12 @@ import org.redisson.connection.ConnectionManager;
import org.redisson.connection.NodeSource;
import org.redisson.connection.NodeSource.Redirect;
import org.redisson.liveobject.core.RedissonObjectBuilder;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
/**
@ -53,7 +51,7 @@ public class RedisCommonBatchExecutor extends RedisExecutor<Object, Void> {
private final AtomicInteger slots;
private final BatchOptions options;
public RedisCommonBatchExecutor(NodeSource source, RPromise<Void> mainPromise,
public RedisCommonBatchExecutor(NodeSource source, CompletableFuture<Void> mainPromise,
ConnectionManager connectionManager, BatchOptions options, Entry entry,
AtomicInteger slots, RedissonObjectBuilder.ReferenceType referenceType, boolean noRetry) {
super(entry.isReadOnlyMode(), source, null, null, null,
@ -93,18 +91,18 @@ public class RedisCommonBatchExecutor extends RedisExecutor<Object, Void> {
}
@Override
protected void sendCommand(RPromise<Void> attemptPromise, RedisConnection connection) {
protected void sendCommand(CompletableFuture<Void> attemptPromise, RedisConnection connection) {
boolean isAtomic = options.getExecutionMode() != ExecutionMode.IN_MEMORY;
boolean isQueued = options.getExecutionMode() == ExecutionMode.REDIS_READ_ATOMIC
|| options.getExecutionMode() == ExecutionMode.REDIS_WRITE_ATOMIC;
List<CommandData<?, ?>> list = new ArrayList<>(entry.getCommands().size());
if (source.getRedirect() == Redirect.ASK) {
RPromise<Void> promise = new RedissonPromise<Void>();
CompletableFuture<Void> promise = new CompletableFuture<Void>();
list.add(new CommandData<>(promise, StringCodec.INSTANCE, RedisCommands.ASKING, new Object[] {}));
}
for (CommandData<?, ?> c : entry.getCommands()) {
if ((c.getPromise().isCancelled() || c.getPromise().isSuccess())
if ((c.getPromise().isCancelled() || (c.getPromise().isDone() && !c.getPromise().isCompletedExceptionally()))
&& !isWaitCommand(c)
&& !isAtomic) {
// skip command
@ -115,7 +113,7 @@ public class RedisCommonBatchExecutor extends RedisExecutor<Object, Void> {
if (list.isEmpty()) {
writeFuture = connection.getChannel().newPromise();
attemptPromise.trySuccess(null);
attemptPromise.complete(null);
timeout.cancel();
return;
}
@ -123,7 +121,7 @@ public class RedisCommonBatchExecutor extends RedisExecutor<Object, Void> {
sendCommand(connection, attemptPromise, list);
}
private void sendCommand(RedisConnection connection, RPromise<Void> attemptPromise, List<CommandData<?, ?>> list) {
private void sendCommand(RedisConnection connection, CompletableFuture<Void> attemptPromise, List<CommandData<?, ?>> list) {
boolean isAtomic = options.getExecutionMode() != ExecutionMode.IN_MEMORY;
boolean isQueued = options.getExecutionMode() == ExecutionMode.REDIS_READ_ATOMIC
|| options.getExecutionMode() == ExecutionMode.REDIS_WRITE_ATOMIC;
@ -131,7 +129,7 @@ public class RedisCommonBatchExecutor extends RedisExecutor<Object, Void> {
CommandData<?, ?> lastCommand = connection.getLastCommand();
if (lastCommand != null && options.isSkipResult()) {
writeFuture = connection.getChannel().newPromise();
lastCommand.getPromise().onComplete((r, e) -> {
lastCommand.getPromise().whenComplete((r, e) -> {
CommandData<?, ?> currentLastCommand = connection.getLastCommand();
if (lastCommand != currentLastCommand && currentLastCommand != null) {
sendCommand(connection, attemptPromise, list);
@ -158,13 +156,13 @@ public class RedisCommonBatchExecutor extends RedisExecutor<Object, Void> {
}
@Override
protected void handleResult(RPromise<Void> attemptPromise, RFuture<RedisConnection> connectionFuture) throws ReflectiveOperationException {
if (attemptPromise.isSuccess()) {
protected void handleResult(CompletableFuture<Void> attemptPromise, CompletableFuture<RedisConnection> connectionFuture) throws ReflectiveOperationException {
if (attemptPromise.isDone() && !attemptPromise.isCompletedExceptionally()) {
if (slots.decrementAndGet() == 0) {
mainPromise.trySuccess(null);
mainPromise.complete(null);
}
} else {
mainPromise.tryFailure(attemptPromise.cause());
mainPromise.completeExceptionally(cause(attemptPromise));
}
}

@ -24,7 +24,6 @@ import io.netty.util.TimerTask;
import io.netty.util.concurrent.FutureListener;
import org.redisson.RedissonShutdownException;
import org.redisson.ScanResult;
import org.redisson.api.RFuture;
import org.redisson.cache.LRUCacheMap;
import org.redisson.client.*;
import org.redisson.client.codec.BaseCodec;
@ -38,16 +37,16 @@ import org.redisson.connection.NodeSource;
import org.redisson.connection.NodeSource.Redirect;
import org.redisson.liveobject.core.RedissonObjectBuilder;
import org.redisson.misc.LogHelper;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedisURI;
import org.redisson.misc.RedissonPromise;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
@ -66,14 +65,14 @@ public class RedisExecutor<V, R> {
final boolean readOnlyMode;
final RedisCommand<V> command;
final Object[] params;
final RPromise<R> mainPromise;
final CompletableFuture<R> mainPromise;
final boolean ignoreRedirect;
final RedissonObjectBuilder objectBuilder;
final ConnectionManager connectionManager;
final RedissonObjectBuilder.ReferenceType referenceType;
final boolean noRetry;
RFuture<RedisConnection> connectionFuture;
CompletableFuture<RedisConnection> connectionFuture;
NodeSource source;
Codec codec;
volatile int attempt;
@ -87,7 +86,7 @@ public class RedisExecutor<V, R> {
long responseTimeout;
public RedisExecutor(boolean readOnlyMode, NodeSource source, Codec codec, RedisCommand<V> command,
Object[] params, RPromise<R> mainPromise, boolean ignoreRedirect,
Object[] params, CompletableFuture<R> mainPromise, boolean ignoreRedirect,
ConnectionManager connectionManager, RedissonObjectBuilder objectBuilder,
RedissonObjectBuilder.ReferenceType referenceType, boolean noRetry) {
super();
@ -116,15 +115,15 @@ public class RedisExecutor<V, R> {
if (!connectionManager.getShutdownLatch().acquire()) {
free();
mainPromise.tryFailure(new RedissonShutdownException("Redisson is shutdown"));
mainPromise.completeExceptionally(new RedissonShutdownException("Redisson is shutdown"));
return;
}
codec = getCodec(codec);
RFuture<RedisConnection> connectionFuture = getConnection();
CompletableFuture<RedisConnection> connectionFuture = getConnection().toCompletableFuture();
RPromise<R> attemptPromise = new RedissonPromise<>();
CompletableFuture<R> attemptPromise = new CompletableFuture<>();
mainPromiseListener = (r, e) -> {
if (mainPromise.isCancelled() && connectionFuture.cancel(false)) {
log.debug("Connection obtaining canceled for {}", command);
@ -136,7 +135,7 @@ public class RedisExecutor<V, R> {
};
if (attempt == 0) {
mainPromise.onComplete((r, e) -> {
mainPromise.whenComplete((r, e) -> {
if (this.mainPromiseListener != null) {
this.mainPromiseListener.accept(r, e);
}
@ -145,13 +144,13 @@ public class RedisExecutor<V, R> {
scheduleRetryTimeout(connectionFuture, attemptPromise);
connectionFuture.onComplete((connection, e) -> {
connectionFuture.whenComplete((connection, e) -> {
if (connectionFuture.isCancelled()) {
connectionManager.getShutdownLatch().release();
return;
}
if (!connectionFuture.isSuccess()) {
if (connectionFuture.isDone() && connectionFuture.isCompletedExceptionally()) {
connectionManager.getShutdownLatch().release();
exception = convertException(connectionFuture);
return;
@ -167,14 +166,14 @@ public class RedisExecutor<V, R> {
});
});
attemptPromise.onComplete((r, e) -> {
attemptPromise.whenComplete((r, e) -> {
releaseConnection(attemptPromise, connectionFuture);
checkAttemptPromise(attemptPromise, connectionFuture);
});
}
private void scheduleRetryTimeout(RFuture<RedisConnection> connectionFuture, RPromise<R> attemptPromise) {
private void scheduleRetryTimeout(CompletableFuture<RedisConnection> connectionFuture, CompletableFuture<R> attemptPromise) {
TimerTask retryTimerTask = new TimerTask() {
@Override
@ -190,7 +189,7 @@ public class RedisExecutor<V, R> {
+ ", command: " + LogHelper.toString(command, params)
+ " after " + attempt + " retry attempts");
} else {
if (connectionFuture.isSuccess()) {
if (connectionFuture.isDone() && !connectionFuture.isCompletedExceptionally()) {
if (writeFuture == null || !writeFuture.isDone()) {
if (attempt == attempts) {
if (writeFuture != null && writeFuture.cancel(false)) {
@ -206,11 +205,11 @@ public class RedisExecutor<V, R> {
exception = new RedisTimeoutException("Command still hasn't been written into connection! " +
"Try to increase nettyThreads setting. Payload size in bytes: " + totalSize
+ ". Node source: " + source + ", connection: " + connectionFuture.getNow()
+ ". Node source: " + source + ", connection: " + getNow(connectionFuture)
+ ", command: " + LogHelper.toString(command, params)
+ " after " + attempt + " retry attempts");
}
attemptPromise.tryFailure(exception);
attemptPromise.completeExceptionally(exception);
}
return;
}
@ -236,7 +235,7 @@ public class RedisExecutor<V, R> {
if (attempt == attempts) {
// filled out in connectionFuture or writeFuture handler
if (exception != null) {
attemptPromise.tryFailure(exception);
attemptPromise.completeExceptionally(exception);
}
return;
}
@ -270,7 +269,7 @@ public class RedisExecutor<V, R> {
}
}
private void checkWriteFuture(ChannelFuture future, RPromise<R> attemptPromise, RedisConnection connection) {
private void checkWriteFuture(ChannelFuture future, CompletableFuture<R> attemptPromise, RedisConnection connection) {
if (future.isCancelled() || attemptPromise.isDone()) {
return;
}
@ -281,7 +280,7 @@ public class RedisExecutor<V, R> {
", command: " + LogHelper.toString(command, params)
+ " after " + attempt + " retry attempts", future.cause());
if (attempt == attempts) {
attemptPromise.tryFailure(exception);
attemptPromise.completeExceptionally(exception);
}
return;
}
@ -291,7 +290,7 @@ public class RedisExecutor<V, R> {
scheduleResponseTimeout(attemptPromise, connection);
}
private void scheduleResponseTimeout(RPromise<R> attemptPromise, RedisConnection connection) {
private void scheduleResponseTimeout(CompletableFuture<R> attemptPromise, RedisConnection connection) {
long timeoutTime = responseTimeout;
if (command != null && command.isBlockingCommand()) {
Long popTimeout = null;
@ -335,7 +334,7 @@ public class RedisExecutor<V, R> {
return;
}
attemptPromise.tryFailure(
attemptPromise.completeExceptionally(
new RedisResponseTimeoutException("Redis server response timeout (" + timeoutAmount + " ms) occured"
+ " after " + attempt + " retry attempts. Increase nettyThreads and/or timeout settings. Try to define pingConnectionInterval setting. Command: "
+ LogHelper.toString(command, params) + ", channel: " + connection.getChannel()));
@ -350,16 +349,16 @@ public class RedisExecutor<V, R> {
&& (command == null || (!command.isBlockingCommand() && !RedisCommands.NO_RETRY.contains(command.getName())));
}
private void handleBlockingOperations(RPromise<R> attemptPromise, RedisConnection connection, Long popTimeout) {
private void handleBlockingOperations(CompletableFuture<R> attemptPromise, RedisConnection connection, Long popTimeout) {
FutureListener<Void> listener = f -> {
mainPromise.tryFailure(new RedissonShutdownException("Redisson is shutdown"));
mainPromise.completeExceptionally(new RedissonShutdownException("Redisson is shutdown"));
};
Timeout scheduledFuture;
if (popTimeout != 0) {
// handling cases when connection has been lost
scheduledFuture = connectionManager.newTimeout(timeout -> {
if (attemptPromise.trySuccess(null)) {
if (attemptPromise.complete(null)) {
connection.forceFastReconnectAsync();
}
}, popTimeout + 1, TimeUnit.SECONDS);
@ -367,7 +366,7 @@ public class RedisExecutor<V, R> {
scheduledFuture = null;
}
mainPromise.onComplete((res, e) -> {
mainPromise.whenComplete((res, e) -> {
if (scheduledFuture != null) {
scheduledFuture.cancel();
}
@ -378,17 +377,17 @@ public class RedisExecutor<V, R> {
// handling cancel operation for blocking commands
if ((mainPromise.isCancelled()
|| mainPromise.cause() instanceof InterruptedException)
|| e instanceof InterruptedException)
&& !attemptPromise.isDone()) {
log.debug("Canceled blocking operation {} used {}", command, connection);
connection.forceFastReconnectAsync().onComplete((r, ex) -> {
connection.forceFastReconnectAsync().whenComplete((r, ex) -> {
attemptPromise.cancel(true);
});
return;
}
if (e instanceof RedissonShutdownException) {
attemptPromise.tryFailure(e);
attemptPromise.completeExceptionally(e);
}
});
@ -399,7 +398,18 @@ public class RedisExecutor<V, R> {
}
}
protected void checkAttemptPromise(RPromise<R> attemptFuture, RFuture<RedisConnection> connectionFuture) {
protected Throwable cause(CompletableFuture<?> future) {
try {
future.getNow(null);
return null;
} catch (CompletionException ex2) {
return ex2.getCause();
} catch (CancellationException ex1) {
return ex1;
}
}
protected void checkAttemptPromise(CompletableFuture<R> attemptFuture, CompletableFuture<RedisConnection> connectionFuture) {
timeout.cancel();
if (attemptFuture.isCancelled()) {
return;
@ -408,10 +418,11 @@ public class RedisExecutor<V, R> {
try {
mainPromiseListener = null;
if (attemptFuture.cause() instanceof RedisMovedException && !ignoreRedirect) {
RedisMovedException ex = (RedisMovedException) attemptFuture.cause();
Throwable cause = cause(attemptFuture);
if (cause instanceof RedisMovedException && !ignoreRedirect) {
RedisMovedException ex = (RedisMovedException) cause;
if (source.getRedirect() == Redirect.MOVED) {
mainPromise.tryFailure(new RedisException("MOVED redirection loop detected. Node " + source.getAddr() + " has further redirect to " + ex.getUrl()));
mainPromise.completeExceptionally(new RedisException("MOVED redirection loop detected. Node " + source.getAddr() + " has further redirect to " + ex.getUrl()));
return;
}
@ -429,8 +440,8 @@ public class RedisExecutor<V, R> {
return;
}
if (attemptFuture.cause() instanceof RedisAskException && !ignoreRedirect) {
RedisAskException ex = (RedisAskException) attemptFuture.cause();
if (cause instanceof RedisAskException && !ignoreRedirect) {
RedisAskException ex = (RedisAskException) cause;
onException();
@ -446,10 +457,10 @@ public class RedisExecutor<V, R> {
return;
}
if (attemptFuture.cause() instanceof RedisLoadingException
|| attemptFuture.cause() instanceof RedisTryAgainException
|| attemptFuture.cause() instanceof RedisClusterDownException
|| attemptFuture.cause() instanceof RedisBusyException) {
if (cause instanceof RedisLoadingException
|| cause instanceof RedisTryAgainException
|| cause instanceof RedisClusterDownException
|| cause instanceof RedisBusyException) {
if (attempt < attempts) {
onException();
connectionManager.newTimeout(timeout -> {
@ -469,49 +480,55 @@ public class RedisExecutor<V, R> {
}
}
protected void handleResult(RPromise<R> attemptPromise, RFuture<RedisConnection> connectionFuture) throws ReflectiveOperationException {
if (attemptPromise.isSuccess()) {
R res = attemptPromise.getNow();
if (res instanceof ScanResult) {
((ScanResult) res).setRedisClient(connectionFuture.getNow().getRedisClient());
}
protected void handleResult(CompletableFuture<R> attemptPromise, CompletableFuture<RedisConnection> connectionFuture) throws ReflectiveOperationException {
R res;
try {
res = attemptPromise.getNow(null);
} catch (CompletionException e) {
handleError(connectionFuture, e.getCause());
return;
} catch (CancellationException e) {
handleError(connectionFuture, e);
return;
}
handleSuccess(mainPromise, connectionFuture, res);
} else {
handleError(connectionFuture, attemptPromise.cause());
if (res instanceof ScanResult) {
((ScanResult) res).setRedisClient(getNow(connectionFuture).getRedisClient());
}
handleSuccess(mainPromise, connectionFuture, res);
}
protected void onException() {
}
protected void handleError(RFuture<RedisConnection> connectionFuture, Throwable cause) {
mainPromise.tryFailure(cause);
protected void handleError(CompletableFuture<RedisConnection> connectionFuture, Throwable cause) {
mainPromise.completeExceptionally(cause);
}
protected void handleSuccess(RPromise<R> promise, RFuture<RedisConnection> connectionFuture, R res) throws ReflectiveOperationException {
protected void handleSuccess(CompletableFuture<R> promise, CompletableFuture<RedisConnection> connectionFuture, R res) throws ReflectiveOperationException {
if (objectBuilder != null) {
handleReference(promise, res);
} else {
promise.trySuccess(res);
promise.complete(res);
}
}
private void handleReference(RPromise<R> promise, R res) throws ReflectiveOperationException {
private void handleReference(CompletableFuture<R> promise, R res) throws ReflectiveOperationException {
if (objectBuilder != null) {
promise.trySuccess((R) objectBuilder.tryHandleReference(res, referenceType));
promise.complete((R) objectBuilder.tryHandleReference(res, referenceType));
} else {
promise.trySuccess(res);
promise.complete(res);
}
}
protected void sendCommand(RPromise<R> attemptPromise, RedisConnection connection) {
protected void sendCommand(CompletableFuture<R> attemptPromise, RedisConnection connection) {
if (source.getRedirect() == Redirect.ASK) {
List<CommandData<?, ?>> list = new ArrayList<>(2);
RPromise<Void> promise = new RedissonPromise<>();
CompletableFuture<Void> promise = new CompletableFuture<>();
list.add(new CommandData<>(promise, codec, RedisCommands.ASKING, new Object[]{}));
list.add(new CommandData<>(attemptPromise, codec, command, params));
RPromise<Void> main = new RedissonPromise<>();
CompletableFuture<Void> main = new CompletableFuture<>();
writeFuture = connection.send(new CommandsData(main, list, false, false));
} else {
if (log.isDebugEnabled()) {
@ -530,12 +547,12 @@ public class RedisExecutor<V, R> {
}
}
protected void releaseConnection(RPromise<R> attemptPromise, RFuture<RedisConnection> connectionFuture) {
if (!connectionFuture.isSuccess()) {
protected void releaseConnection(CompletableFuture<R> attemptPromise, CompletableFuture<RedisConnection> connectionFuture) {
if (connectionFuture.isDone() && connectionFuture.isCompletedExceptionally()) {
return;
}
RedisConnection connection = connectionFuture.getNow();
RedisConnection connection = getNow(connectionFuture);
connectionManager.getShutdownLatch().release();
if (connectionManager.getConfig().getMasterConnectionPoolSize() < 10) {
if (source.getRedirect() == Redirect.ASK || getClass() != RedisExecutor.class) {
@ -565,10 +582,10 @@ public class RedisExecutor<V, R> {
}
public RedisClient getRedisClient() {
return connectionFuture.getNow().getRedisClient();
return getNow(connectionFuture).getRedisClient();
}
protected RFuture<RedisConnection> getConnection() {
protected CompletableFuture<RedisConnection> getConnection() {
if (readOnlyMode) {
connectionFuture = connectionManager.connectionReadOp(source, command);
} else {
@ -615,11 +632,20 @@ public class RedisExecutor<V, R> {
return codecToUse;
}
protected <T> RedisException convertException(RFuture<T> future) {
if (future.cause() instanceof RedisException) {
return (RedisException) future.cause();
protected <T> T getNow(CompletableFuture<T> future) {
try {
return future.getNow(null);
} catch (Exception e) {
return null;
}
}
protected <T> RedisException convertException(CompletableFuture<T> future) {
Throwable cause = cause(future);
if (cause instanceof RedisException) {
return (RedisException) cause;
}
return new RedisException("Unexpected exception while processing command", future.cause());
return new RedisException("Unexpected exception while processing command", cause);
}

@ -17,7 +17,6 @@ package org.redisson.command;
import org.redisson.api.BatchOptions;
import org.redisson.api.BatchOptions.ExecutionMode;
import org.redisson.api.RFuture;
import org.redisson.client.RedisConnection;
import org.redisson.client.codec.Codec;
import org.redisson.client.protocol.*;
@ -30,12 +29,12 @@ import org.redisson.connection.NodeSource.Redirect;
import org.redisson.liveobject.core.RedissonObjectBuilder;
import org.redisson.misc.AsyncCountDownLatch;
import org.redisson.misc.LogHelper;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@ -54,7 +53,7 @@ public class RedisQueuedBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R>
@SuppressWarnings("ParameterNumber")
public RedisQueuedBatchExecutor(boolean readOnlyMode, NodeSource source, Codec codec, RedisCommand<V> command,
Object[] params, RPromise<R> mainPromise, boolean ignoreRedirect, ConnectionManager connectionManager,
Object[] params, CompletableFuture<R> mainPromise, boolean ignoreRedirect, ConnectionManager connectionManager,
RedissonObjectBuilder objectBuilder, ConcurrentMap<MasterSlaveEntry, Entry> commands,
ConcurrentMap<MasterSlaveEntry, ConnectionEntry> connections, BatchOptions options, AtomicInteger index,
AtomicBoolean executed, AsyncCountDownLatch latch, RedissonObjectBuilder.ReferenceType referenceType,
@ -79,7 +78,7 @@ public class RedisQueuedBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R>
@Override
protected void releaseConnection(RPromise<R> attemptPromise, RFuture<RedisConnection> connectionFuture) {
protected void releaseConnection(CompletableFuture<R> attemptPromise, CompletableFuture<RedisConnection> connectionFuture) {
if (RedisCommands.EXEC.getName().equals(command.getName())
|| RedisCommands.DISCARD.getName().equals(command.getName())) {
super.releaseConnection(attemptPromise, connectionFuture);
@ -89,7 +88,7 @@ public class RedisQueuedBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R>
}
@Override
protected void handleSuccess(RPromise<R> promise, RFuture<RedisConnection> connectionFuture, R res)
protected void handleSuccess(CompletableFuture<R> promise, CompletableFuture<RedisConnection> connectionFuture, R res)
throws ReflectiveOperationException {
if (RedisCommands.EXEC.getName().equals(command.getName())) {
super.handleSuccess(promise, connectionFuture, res);
@ -102,7 +101,7 @@ public class RedisQueuedBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R>
try {
BatchPromise<R> batchPromise = (BatchPromise<R>) promise;
RPromise<R> sentPromise = (RPromise<R>) batchPromise.getSentPromise();
CompletableFuture sentPromise = batchPromise.getSentPromise();
super.handleSuccess(sentPromise, connectionFuture, null);
} finally {
latch.countDown();
@ -110,15 +109,15 @@ public class RedisQueuedBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R>
}
@Override
protected void handleError(RFuture<RedisConnection> connectionFuture, Throwable cause) {
protected void handleError(CompletableFuture<RedisConnection> connectionFuture, Throwable cause) {
try {
if (mainPromise instanceof BatchPromise) {
BatchPromise<R> batchPromise = (BatchPromise<R>) mainPromise;
RPromise<R> sentPromise = (RPromise<R>) batchPromise.getSentPromise();
sentPromise.tryFailure(cause);
mainPromise.tryFailure(cause);
CompletableFuture sentPromise = batchPromise.getSentPromise();
sentPromise.completeExceptionally(cause);
mainPromise.completeExceptionally(cause);
if (executed.compareAndSet(false, true)) {
connectionFuture.getNow().forceFastReconnectAsync().onComplete((res, e) -> {
getNow(connectionFuture).forceFastReconnectAsync().whenComplete((res, e) -> {
RedisQueuedBatchExecutor.super.releaseConnection(mainPromise, connectionFuture);
});
}
@ -132,7 +131,7 @@ public class RedisQueuedBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R>
}
@Override
protected void sendCommand(RPromise<R> attemptPromise, RedisConnection connection) {
protected void sendCommand(CompletableFuture<R> attemptPromise, RedisConnection connection) {
MasterSlaveEntry msEntry = getEntry(source);
ConnectionEntry connectionEntry = connections.get(msEntry);
@ -140,14 +139,14 @@ public class RedisQueuedBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R>
if (source.getRedirect() == Redirect.ASK) {
List<CommandData<?, ?>> list = new ArrayList<CommandData<?, ?>>(2);
RPromise<Void> promise = new RedissonPromise<Void>();
list.add(new CommandData<Void, Void>(promise, codec, RedisCommands.ASKING, new Object[]{}));
CompletableFuture<Void> promise = new CompletableFuture<>();
list.add(new CommandData<>(promise, codec, RedisCommands.ASKING, new Object[]{}));
if (connectionEntry.isFirstCommand()) {
list.add(new CommandData<Void, Void>(promise, codec, RedisCommands.MULTI, new Object[]{}));
list.add(new CommandData<>(promise, codec, RedisCommands.MULTI, new Object[]{}));
connectionEntry.setFirstCommand(false);
}
list.add(new CommandData<V, R>(attemptPromise, codec, command, params));
RPromise<Void> main = new RedissonPromise<Void>();
CompletableFuture<Void> main = new CompletableFuture<>();
writeFuture = connection.send(new CommandsData(main, list, true, syncSlaves));
} else {
if (log.isDebugEnabled()) {
@ -157,9 +156,9 @@ public class RedisQueuedBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R>
if (connectionEntry.isFirstCommand()) {
List<CommandData<?, ?>> list = new ArrayList<CommandData<?, ?>>(2);
list.add(new CommandData<Void, Void>(new RedissonPromise<Void>(), codec, RedisCommands.MULTI, new Object[]{}));
list.add(new CommandData<V, R>(attemptPromise, codec, command, params));
RPromise<Void> main = new RedissonPromise<Void>();
list.add(new CommandData<>(new RedissonPromise<Void>(), codec, RedisCommands.MULTI, new Object[]{}));
list.add(new CommandData<>(attemptPromise, codec, command, params));
CompletableFuture<Void> main = new CompletableFuture<>();
writeFuture = connection.send(new CommandsData(main, list, true, syncSlaves));
connectionEntry.setFirstCommand(false);
} else {
@ -184,13 +183,13 @@ public class RedisQueuedBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R>
entry.getCommands().add(waitCommand);
}
RPromise<Void> main = new RedissonPromise<Void>();
CompletableFuture<Void> main = new CompletableFuture<>();
writeFuture = connection.send(new CommandsData(main, list, new ArrayList(entry.getCommands()),
options.isSkipResult(), false, true, syncSlaves));
} else {
RPromise<Void> main = new RedissonPromise<Void>();
CompletableFuture<Void> main = new CompletableFuture<>();
List<CommandData<?, ?>> list = new ArrayList<>();
list.add(new CommandData<V, R>(attemptPromise, codec, command, params));
list.add(new CommandData<>(attemptPromise, codec, command, params));
writeFuture = connection.send(new CommandsData(main, list, true, syncSlaves));
}
}
@ -198,7 +197,7 @@ public class RedisQueuedBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R>
}
@Override
protected RFuture<RedisConnection> getConnection() {
protected CompletableFuture<RedisConnection> getConnection() {
MasterSlaveEntry msEntry = getEntry(source);
ConnectionEntry entry = connections.get(msEntry);
if (entry == null) {
@ -219,7 +218,7 @@ public class RedisQueuedBatchExecutor<V, R> extends BaseRedisBatchExecutor<V, R>
return entry.getConnectionFuture();
}
RFuture<RedisConnection> connectionFuture;
CompletableFuture<RedisConnection> connectionFuture;
if (this.options.getExecutionMode() == ExecutionMode.REDIS_WRITE_ATOMIC) {
connectionFuture = connectionManager.connectionWriteOp(source, null);
} else {

@ -21,7 +21,6 @@ import io.netty.util.TimerTask;
import io.netty.util.concurrent.Future;
import org.redisson.ElementsSubscribeService;
import org.redisson.api.NodeType;
import org.redisson.api.RFuture;
import org.redisson.client.RedisClient;
import org.redisson.client.RedisConnection;
import org.redisson.client.RedisNodeNotFoundException;
@ -92,9 +91,9 @@ public interface ConnectionManager {
void releaseWrite(NodeSource source, RedisConnection connection);
RFuture<RedisConnection> connectionReadOp(NodeSource source, RedisCommand<?> command);
CompletableFuture<RedisConnection> connectionReadOp(NodeSource source, RedisCommand<?> command);
RFuture<RedisConnection> connectionWriteOp(NodeSource source, RedisCommand<?> command);
CompletableFuture<RedisConnection> connectionWriteOp(NodeSource source, RedisCommand<?> command);
RedisClient createClient(NodeType type, RedisURI address, int timeout, int commandTimeout, String sslHostname);

@ -40,7 +40,6 @@ import io.netty.util.internal.PlatformDependent;
import org.redisson.ElementsSubscribeService;
import org.redisson.Version;
import org.redisson.api.NodeType;
import org.redisson.api.RFuture;
import org.redisson.client.*;
import org.redisson.client.codec.Codec;
import org.redisson.client.protocol.RedisCommand;
@ -48,7 +47,6 @@ import org.redisson.cluster.ClusterSlotRange;
import org.redisson.config.*;
import org.redisson.misc.InfinitySemaphoreLatch;
import org.redisson.misc.RedisURI;
import org.redisson.misc.RedissonPromise;
import org.redisson.pubsub.PublishSubscribeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -504,10 +502,12 @@ public class MasterSlaveConnectionManager implements ConnectionManager {
}
@Override
public RFuture<RedisConnection> connectionWriteOp(NodeSource source, RedisCommand<?> command) {
public CompletableFuture<RedisConnection> connectionWriteOp(NodeSource source, RedisCommand<?> command) {
MasterSlaveEntry entry = getEntry(source);
if (entry == null) {
return RedissonPromise.newFailedFuture(createNodeNotFoundException(source));
CompletableFuture<RedisConnection> f = new CompletableFuture<>();
f.completeExceptionally(createNodeNotFoundException(source));
return f;
}
// fix for https://github.com/redisson/redisson/issues/1548
if (source.getRedirect() != null
@ -534,10 +534,12 @@ public class MasterSlaveConnectionManager implements ConnectionManager {
}
@Override
public RFuture<RedisConnection> connectionReadOp(NodeSource source, RedisCommand<?> command) {
public CompletableFuture<RedisConnection> connectionReadOp(NodeSource source, RedisCommand<?> command) {
MasterSlaveEntry entry = getEntry(source);
if (entry == null) {
return RedissonPromise.newFailedFuture(createNodeNotFoundException(source));
CompletableFuture<RedisConnection> f = new CompletableFuture<>();
f.completeExceptionally(createNodeNotFoundException(source));
return f;
}
if (source.getRedirect() != null) {

@ -17,7 +17,6 @@ package org.redisson.connection;
import io.netty.channel.ChannelFuture;
import org.redisson.api.NodeType;
import org.redisson.api.RFuture;
import org.redisson.client.RedisClient;
import org.redisson.client.RedisConnection;
import org.redisson.client.RedisPubSubConnection;
@ -254,8 +253,8 @@ public class MasterSlaveEntry {
return;
}
RFuture<RedisConnection> newConnectionFuture = entry.connectionWriteOp(commandData.getCommand());
newConnectionFuture.onComplete((newConnection, e) -> {
CompletableFuture<RedisConnection> newConnectionFuture = entry.connectionWriteOp(commandData.getCommand());
newConnectionFuture.whenComplete((newConnection, e) -> {
if (e != null) {
connectionManager.newTimeout(timeout ->
reattachBlockingQueue(commandData), 1, TimeUnit.SECONDS);
@ -274,7 +273,7 @@ public class MasterSlaveEntry {
reattachBlockingQueue(commandData), 1, TimeUnit.SECONDS);
}
});
commandData.getPromise().onComplete((r, ex) -> {
commandData.getPromise().whenComplete((r, ex) -> {
entry.releaseWrite(newConnection);
});
});
@ -483,33 +482,33 @@ public class MasterSlaveEntry {
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
}
public RFuture<RedisConnection> connectionWriteOp(RedisCommand<?> command) {
public CompletableFuture<RedisConnection> connectionWriteOp(RedisCommand<?> command) {
return writeConnectionPool.get(command);
}
public RFuture<RedisConnection> redirectedConnectionWriteOp(RedisCommand<?> command, RedisURI addr) {
public CompletableFuture<RedisConnection> redirectedConnectionWriteOp(RedisCommand<?> command, RedisURI addr) {
return slaveBalancer.getConnection(command, addr);
}
public RFuture<RedisConnection> connectionReadOp(RedisCommand<?> command) {
public CompletableFuture<RedisConnection> connectionReadOp(RedisCommand<?> command) {
if (config.getReadMode() == ReadMode.MASTER) {
return connectionWriteOp(command);
}
return slaveBalancer.nextConnection(command);
}
public RFuture<RedisConnection> connectionReadOp(RedisCommand<?> command, RedisURI addr) {
public CompletableFuture<RedisConnection> connectionReadOp(RedisCommand<?> command, RedisURI addr) {
return slaveBalancer.getConnection(command, addr);
}
public RFuture<RedisConnection> connectionReadOp(RedisCommand<?> command, RedisClient client) {
public CompletableFuture<RedisConnection> connectionReadOp(RedisCommand<?> command, RedisClient client) {
if (config.getReadMode() == ReadMode.MASTER) {
return connectionWriteOp(command);
}
return slaveBalancer.getConnection(command, client);
}
public RFuture<RedisPubSubConnection> nextPubSubConnection() {
public CompletableFuture<RedisPubSubConnection> nextPubSubConnection() {
if (config.getSubscriptionMode() == SubscriptionMode.MASTER) {
return pubSubConnectionPool.get();
}

@ -15,12 +15,13 @@
*/
package org.redisson.connection;
import org.redisson.api.RFuture;
import org.redisson.client.RedisConnection;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.config.MasterSlaveServersConfig;
import org.redisson.misc.RedisURI;
import java.util.concurrent.CompletableFuture;
/**
*
* @author Nikita Koksharov
@ -33,12 +34,12 @@ public class SingleEntry extends MasterSlaveEntry {
}
@Override
public RFuture<RedisConnection> connectionReadOp(RedisCommand<?> command, RedisURI addr) {
public CompletableFuture<RedisConnection> connectionReadOp(RedisCommand<?> command, RedisURI addr) {
return super.connectionWriteOp(command);
}
@Override
public RFuture<RedisConnection> connectionReadOp(RedisCommand<?> command) {
public CompletableFuture<RedisConnection> connectionReadOp(RedisCommand<?> command) {
return super.connectionWriteOp(command);
}

@ -16,7 +16,6 @@
package org.redisson.connection.balancer;
import org.redisson.api.NodeType;
import org.redisson.api.RFuture;
import org.redisson.client.RedisClient;
import org.redisson.client.RedisConnection;
import org.redisson.client.RedisConnectionException;
@ -31,7 +30,6 @@ import org.redisson.connection.MasterSlaveEntry;
import org.redisson.connection.pool.PubSubConnectionPool;
import org.redisson.connection.pool.SlaveConnectionPool;
import org.redisson.misc.RedisURI;
import org.redisson.misc.RedissonPromise;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -191,7 +189,7 @@ public class LoadBalancerManager {
return connectionEntry;
}
public RFuture<RedisPubSubConnection> nextPubSubConnection() {
public CompletableFuture<RedisPubSubConnection> nextPubSubConnection() {
return pubSubConnectionPool.get();
}
@ -236,25 +234,29 @@ public class LoadBalancerManager {
return client2Entry.get(redisClient);
}
public RFuture<RedisConnection> getConnection(RedisCommand<?> command, RedisURI addr) {
public CompletableFuture<RedisConnection> getConnection(RedisCommand<?> command, RedisURI addr) {
ClientConnectionsEntry entry = getEntry(addr);
if (entry != null) {
return slaveConnectionPool.get(command, entry);
}
RedisConnectionException exception = new RedisConnectionException("Can't find entry for " + addr);
return RedissonPromise.newFailedFuture(exception);
CompletableFuture<RedisConnection> f = new CompletableFuture<>();
f.completeExceptionally(exception);
return f;
}
public RFuture<RedisConnection> getConnection(RedisCommand<?> command, RedisClient client) {
public CompletableFuture<RedisConnection> getConnection(RedisCommand<?> command, RedisClient client) {
ClientConnectionsEntry entry = getEntry(client);
if (entry != null) {
return slaveConnectionPool.get(command, entry);
}
RedisConnectionException exception = new RedisConnectionException("Can't find entry for " + client);
return RedissonPromise.newFailedFuture(exception);
CompletableFuture<RedisConnection> f = new CompletableFuture<>();
f.completeExceptionally(exception);
return f;
}
public RFuture<RedisConnection> nextConnection(RedisCommand<?> command) {
public CompletableFuture<RedisConnection> nextConnection(RedisCommand<?> command) {
return slaveConnectionPool.get(command);
}

@ -26,8 +26,6 @@ import org.redisson.connection.ClientConnectionsEntry;
import org.redisson.connection.ClientConnectionsEntry.FreezeReason;
import org.redisson.connection.ConnectionManager;
import org.redisson.connection.MasterSlaveEntry;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -112,9 +110,9 @@ abstract class ConnectionPool<T extends RedisConnection> {
@Override
public void run() {
RPromise<T> promise = new RedissonPromise<T>();
CompletableFuture<T> promise = new CompletableFuture<T>();
createConnection(entry, promise);
promise.onComplete((conn, e) -> {
promise.whenComplete((conn, e) -> {
if (e == null) {
if (!initPromise.isDone()) {
entry.addConnection(conn);
@ -178,7 +176,7 @@ abstract class ConnectionPool<T extends RedisConnection> {
protected abstract int getMinimumIdleSize(ClientConnectionsEntry entry);
public RFuture<T> get(RedisCommand<?> command) {
public CompletableFuture<T> get(RedisCommand<?> command) {
List<ClientConnectionsEntry> entriesCopy = new LinkedList<ClientConnectionsEntry>(entries);
for (Iterator<ClientConnectionsEntry> iterator = entriesCopy.iterator(); iterator.hasNext();) {
ClientConnectionsEntry entry = iterator.next();
@ -211,10 +209,12 @@ abstract class ConnectionPool<T extends RedisConnection> {
}
RedisConnectionException exception = new RedisConnectionException(errorMsg.toString());
return RedissonPromise.newFailedFuture(exception);
CompletableFuture<T> result = new CompletableFuture<>();
result.completeExceptionally(exception);
return result;
}
public RFuture<T> get(RedisCommand<?> command, ClientConnectionsEntry entry) {
public CompletableFuture<T> get(RedisCommand<?> command, ClientConnectionsEntry entry) {
return acquireConnection(command, entry);
}
@ -222,8 +222,8 @@ abstract class ConnectionPool<T extends RedisConnection> {
}
protected final RFuture<T> acquireConnection(RedisCommand<?> command, ClientConnectionsEntry entry) {
RPromise<T> result = new RedissonPromise<T>();
protected final CompletableFuture<T> acquireConnection(RedisCommand<?> command, ClientConnectionsEntry entry) {
CompletableFuture<T> result = new CompletableFuture<T>();
Runnable callback = () -> {
connectTo(entry, result, command);
@ -248,7 +248,7 @@ abstract class ConnectionPool<T extends RedisConnection> {
return (CompletionStage<T>) entry.connect();
}
private void connectTo(ClientConnectionsEntry entry, RPromise<T> promise, RedisCommand<?> command) {
private void connectTo(ClientConnectionsEntry entry, CompletableFuture<T> promise, RedisCommand<?> command) {
if (promise.isDone()) {
connectionManager.getGroup().submit(() -> {
releaseConnection(entry);
@ -269,7 +269,7 @@ abstract class ConnectionPool<T extends RedisConnection> {
createConnection(entry, promise);
}
private void createConnection(ClientConnectionsEntry entry, RPromise<T> promise) {
private void createConnection(ClientConnectionsEntry entry, CompletableFuture<T> promise) {
CompletionStage<T> connFuture = connect(entry);
connFuture.whenComplete((conn, e) -> {
if (e != null) {
@ -286,18 +286,18 @@ abstract class ConnectionPool<T extends RedisConnection> {
});
}
private void connectedSuccessful(ClientConnectionsEntry entry, RPromise<T> promise, T conn) {
private void connectedSuccessful(ClientConnectionsEntry entry, CompletableFuture<T> promise, T conn) {
if (conn.isActive() && entry.getNodeType() == NodeType.SLAVE) {
entry.resetFirstFail();
}
if (!promise.trySuccess(conn)) {
if (!promise.complete(conn)) {
releaseConnection(entry, conn);
releaseConnection(entry);
}
}
private void promiseFailure(ClientConnectionsEntry entry, RPromise<T> promise, Throwable cause) {
private void promiseFailure(ClientConnectionsEntry entry, CompletableFuture<T> promise, Throwable cause) {
if (entry.getNodeType() == NodeType.SLAVE) {
entry.trySetupFistFail();
if (entry.isFailed()) {
@ -307,10 +307,10 @@ abstract class ConnectionPool<T extends RedisConnection> {
releaseConnection(entry);
promise.tryFailure(cause);
promise.completeExceptionally(cause);
}
private void promiseFailure(ClientConnectionsEntry entry, RPromise<T> promise, T conn) {
private void promiseFailure(ClientConnectionsEntry entry, CompletableFuture<T> promise, T conn) {
if (entry.getNodeType() == NodeType.SLAVE) {
entry.trySetupFistFail();
if (entry.isFailed()) {
@ -327,7 +327,7 @@ abstract class ConnectionPool<T extends RedisConnection> {
releaseConnection(entry);
RedisConnectionException cause = new RedisConnectionException(conn + " is not active!");
promise.tryFailure(cause);
promise.completeExceptionally(cause);
}
private void checkForReconnect(ClientConnectionsEntry entry, Throwable cause) {

@ -15,7 +15,6 @@
*/
package org.redisson.connection.pool;
import org.redisson.api.RFuture;
import org.redisson.client.RedisConnection;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.config.MasterSlaveServersConfig;
@ -23,6 +22,8 @@ import org.redisson.connection.ClientConnectionsEntry;
import org.redisson.connection.ConnectionManager;
import org.redisson.connection.MasterSlaveEntry;
import java.util.concurrent.CompletableFuture;
/**
* Connection pool for master node
@ -37,7 +38,7 @@ public class MasterConnectionPool extends ConnectionPool<RedisConnection> {
}
@Override
public RFuture<RedisConnection> get(RedisCommand<?> command) {
public CompletableFuture<RedisConnection> get(RedisCommand<?> command) {
return acquireConnection(command, entries.peek());
}

@ -15,7 +15,6 @@
*/
package org.redisson.connection.pool;
import org.redisson.api.RFuture;
import org.redisson.client.RedisPubSubConnection;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.config.MasterSlaveServersConfig;
@ -23,6 +22,8 @@ import org.redisson.connection.ClientConnectionsEntry;
import org.redisson.connection.ConnectionManager;
import org.redisson.connection.MasterSlaveEntry;
import java.util.concurrent.CompletableFuture;
/**
* Connection pool for Publish/Subscribe used with single node
*
@ -37,7 +38,7 @@ public class MasterPubSubConnectionPool extends PubSubConnectionPool {
}
@Override
public RFuture<RedisPubSubConnection> get(RedisCommand<?> command) {
public CompletableFuture<RedisPubSubConnection> get(RedisCommand<?> command) {
return acquireConnection(command, entries.peek());
}

@ -15,7 +15,6 @@
*/
package org.redisson.connection.pool;
import org.redisson.api.RFuture;
import org.redisson.client.RedisPubSubConnection;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.client.protocol.RedisCommands;
@ -24,6 +23,7 @@ import org.redisson.connection.ClientConnectionsEntry;
import org.redisson.connection.ConnectionManager;
import org.redisson.connection.MasterSlaveEntry;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
/**
@ -38,7 +38,7 @@ public class PubSubConnectionPool extends ConnectionPool<RedisPubSubConnection>
super(config, connectionManager, masterSlaveEntry);
}
public RFuture<RedisPubSubConnection> get() {
public CompletableFuture<RedisPubSubConnection> get() {
return get(RedisCommands.PUBLISH);
}

@ -16,7 +16,8 @@
package org.redisson.pubsub;
import org.redisson.RedissonCountDownLatchEntry;
import org.redisson.misc.RPromise;
import java.util.concurrent.CompletableFuture;
/**
*
@ -33,7 +34,7 @@ public class CountDownLatchPubSub extends PublishSubscribe<RedissonCountDownLatc
}
@Override
protected RedissonCountDownLatchEntry createEntry(RPromise<RedissonCountDownLatchEntry> newPromise) {
protected RedissonCountDownLatchEntry createEntry(CompletableFuture<RedissonCountDownLatchEntry> newPromise) {
return new RedissonCountDownLatchEntry(newPromise);
}

@ -16,7 +16,8 @@
package org.redisson.pubsub;
import org.redisson.RedissonLockEntry;
import org.redisson.misc.RPromise;
import java.util.concurrent.CompletableFuture;
/**
*
@ -33,7 +34,7 @@ public class LockPubSub extends PublishSubscribe<RedissonLockEntry> {
}
@Override
protected RedissonLockEntry createEntry(RPromise<RedissonLockEntry> newPromise) {
protected RedissonLockEntry createEntry(CompletableFuture<RedissonLockEntry> newPromise) {
return new RedissonLockEntry(newPromise);
}

@ -16,16 +16,13 @@
package org.redisson.pubsub;
import org.redisson.PubSubEntry;
import org.redisson.api.RFuture;
import org.redisson.client.BaseRedisPubSubListener;
import org.redisson.client.ChannelName;
import org.redisson.client.RedisPubSubListener;
import org.redisson.client.codec.LongCodec;
import org.redisson.client.protocol.pubsub.PubSubType;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import org.redisson.misc.TransferListener;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@ -64,21 +61,21 @@ abstract class PublishSubscribe<E extends PubSubEntry<E>> {
}
public RFuture<E> subscribe(String entryName, String channelName) {
public CompletableFuture<E> subscribe(String entryName, String channelName) {
AsyncSemaphore semaphore = service.getSemaphore(new ChannelName(channelName));
RPromise<E> newPromise = new RedissonPromise<>();
CompletableFuture<E> newPromise = new CompletableFuture<>();
semaphore.acquire(() -> {
if (!newPromise.setUncancellable()) {
semaphore.release();
return;
}
E entry = entries.get(entryName);
if (entry != null) {
entry.acquire();
semaphore.release();
entry.getPromise().onComplete(new TransferListener<E>(newPromise));
return;
entry.getPromise().whenComplete((r, e) -> {
if (e != null) {
newPromise.completeExceptionally(e);
return;
}
newPromise.complete(r);
});
}
E value = createEntry(newPromise);
@ -88,7 +85,13 @@ abstract class PublishSubscribe<E extends PubSubEntry<E>> {
if (oldValue != null) {
oldValue.acquire();
semaphore.release();
oldValue.getPromise().onComplete(new TransferListener<E>(newPromise));
oldValue.getPromise().whenComplete((r, e) -> {
if (e != null) {
newPromise.completeExceptionally(e);
return;
}
newPromise.complete(r);
});
return;
}
@ -99,7 +102,7 @@ abstract class PublishSubscribe<E extends PubSubEntry<E>> {
return newPromise;
}
protected abstract E createEntry(RPromise<E> newPromise);
protected abstract E createEntry(CompletableFuture<E> newPromise);
protected abstract void onMessage(E value, Long message);
@ -122,7 +125,7 @@ abstract class PublishSubscribe<E extends PubSubEntry<E>> {
}
if (type == PubSubType.SUBSCRIBE) {
value.getPromise().trySuccess(value);
value.getPromise().complete(value);
return true;
}
return false;

@ -32,12 +32,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
*
@ -140,7 +138,7 @@ public class PublishSubscribeService {
return name2PubSubConnection.get(createKey(channelName));
}
public RFuture<Collection<PubSubConnectionEntry>> psubscribe(ChannelName channelName, Codec codec, RedisPubSubListener<?>... listeners) {
public CompletableFuture<Collection<PubSubConnectionEntry>> psubscribe(ChannelName channelName, Codec codec, RedisPubSubListener<?>... listeners) {
if (isMultiEntity(channelName)) {
Collection<MasterSlaveEntry> entrySet = connectionManager.getEntrySet();
@ -160,36 +158,19 @@ public class PublishSubscribeService {
return l;
}).toArray(RedisPubSubListener[]::new);
RPromise<Collection<PubSubConnectionEntry>> result = new RedissonPromise<>();
Collection<PubSubConnectionEntry> entries = new ConcurrentLinkedQueue<>();
AtomicInteger counter = new AtomicInteger(entrySet.size());
List<CompletableFuture<PubSubConnectionEntry>> futures = new ArrayList<>();
for (MasterSlaveEntry entry : entrySet) {
RFuture<PubSubConnectionEntry> future = subscribe(PubSubType.PSUBSCRIBE, codec, channelName, entry, ls);
future.onComplete((res, e) -> {
if (e != null) {
result.tryFailure(e);
return;
}
entries.add(res);
if (counter.decrementAndGet() == 0) {
result.trySuccess(entries);
}
});
CompletableFuture<PubSubConnectionEntry> future = subscribe(PubSubType.PSUBSCRIBE, codec, channelName, entry, ls);
futures.add(future);
}
return result;
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
return future.thenApply(r -> {
return futures.stream().map(v -> v.getNow(null)).collect(Collectors.toList());
});
}
RPromise<Collection<PubSubConnectionEntry>> result = new RedissonPromise<>();
RFuture<PubSubConnectionEntry> f = subscribe(PubSubType.PSUBSCRIBE, codec, channelName, getEntry(channelName), listeners);
f.onComplete((res, e) -> {
if (e != null) {
result.tryFailure(e);
return;
}
result.trySuccess(Collections.singletonList(res));
});
return result;
CompletableFuture<PubSubConnectionEntry> f = subscribe(PubSubType.PSUBSCRIBE, codec, channelName, getEntry(channelName), listeners);
return f.thenApply(res -> Collections.singletonList(res));
}
private boolean isMultiEntity(ChannelName channelName) {
@ -198,12 +179,12 @@ public class PublishSubscribeService {
|| channelName.toString().startsWith("__keyevent@"));
}
public RFuture<PubSubConnectionEntry> subscribe(Codec codec, ChannelName channelName, RedisPubSubListener<?>... listeners) {
public CompletableFuture<PubSubConnectionEntry> subscribe(Codec codec, ChannelName channelName, RedisPubSubListener<?>... listeners) {
return subscribe(PubSubType.SUBSCRIBE, codec, channelName, getEntry(channelName), listeners);
}
private RFuture<PubSubConnectionEntry> subscribe(PubSubType type, Codec codec, ChannelName channelName, MasterSlaveEntry entry, RedisPubSubListener<?>... listeners) {
RPromise<PubSubConnectionEntry> promise = new RedissonPromise<>();
private CompletableFuture<PubSubConnectionEntry> subscribe(PubSubType type, Codec codec, ChannelName channelName, MasterSlaveEntry entry, RedisPubSubListener<?>... listeners) {
CompletableFuture<PubSubConnectionEntry> promise = new CompletableFuture<>();
AsyncSemaphore lock = getSemaphore(channelName);
lock.acquire(() -> {
if (promise.isDone()) {
@ -216,8 +197,8 @@ public class PublishSubscribeService {
return promise;
}
public RFuture<PubSubConnectionEntry> subscribe(Codec codec, String channelName, AsyncSemaphore semaphore, RedisPubSubListener<?>... listeners) {
RPromise<PubSubConnectionEntry> promise = new RedissonPromise<>();
public CompletableFuture<PubSubConnectionEntry> subscribe(Codec codec, String channelName, AsyncSemaphore semaphore, RedisPubSubListener<?>... listeners) {
CompletableFuture<PubSubConnectionEntry> promise = new CompletableFuture<>();
subscribe(codec, new ChannelName(channelName), getEntry(new ChannelName(channelName)), promise, PubSubType.SUBSCRIBE, semaphore, listeners);
return promise;
}
@ -232,7 +213,7 @@ public class PublishSubscribeService {
}
private void subscribe(Codec codec, ChannelName channelName, MasterSlaveEntry entry,
RPromise<PubSubConnectionEntry> promise, PubSubType type,
CompletableFuture<PubSubConnectionEntry> promise, PubSubType type,
AsyncSemaphore lock, RedisPubSubListener<?>... listeners) {
PubSubConnectionEntry connEntry = name2PubSubConnection.get(new PubSubKey(channelName, entry));
if (connEntry != null) {
@ -277,7 +258,7 @@ public class PublishSubscribeService {
}
freePubSubLock.release();
RFuture<Void> subscribeFuture = addListeners(channelName, promise, type, lock, freeEntry, listeners);
CompletableFuture<Void> subscribeFuture = addListeners(channelName, promise, type, lock, freeEntry, listeners);
ChannelFuture future;
if (PubSubType.PSUBSCRIBE == type) {
@ -306,17 +287,17 @@ public class PublishSubscribeService {
return connectionManager.getEntry(slot);
}
private RFuture<Void> addListeners(ChannelName channelName, RPromise<PubSubConnectionEntry> promise,
private CompletableFuture<Void> addListeners(ChannelName channelName, CompletableFuture<PubSubConnectionEntry> promise,
PubSubType type, AsyncSemaphore lock, PubSubConnectionEntry connEntry,
RedisPubSubListener<?>... listeners) {
for (RedisPubSubListener<?> listener : listeners) {
connEntry.addListener(channelName, listener);
}
SubscribeListener list = connEntry.getSubscribeFuture(channelName, type);
RFuture<Void> subscribeFuture = list.getSuccessFuture();
CompletableFuture<Void> subscribeFuture = list.getSuccessFuture();
subscribeFuture.onComplete((res, e) -> {
if (!promise.trySuccess(connEntry)) {
return subscribeFuture.whenComplete((res, e) -> {
if (!promise.complete(connEntry)) {
for (RedisPubSubListener<?> listener : listeners) {
connEntry.removeListener(channelName, listener);
}
@ -332,31 +313,31 @@ public class PublishSubscribeService {
lock.release();
}
});
return subscribeFuture;
}
private RFuture<RedisPubSubConnection> nextPubSubConnection(MasterSlaveEntry entry, ChannelName channelName) {
private CompletionStage<RedisPubSubConnection> nextPubSubConnection(MasterSlaveEntry entry, ChannelName channelName) {
if (entry == null) {
int slot = connectionManager.calcSlot(channelName.getName());
RedisNodeNotFoundException ex = new RedisNodeNotFoundException("Node for slot: " + slot + " hasn't been discovered yet. Check cluster slots coverage using CLUSTER NODES command. Increase value of retryAttempts and/or retryInterval settings.");
return RedissonPromise.newFailedFuture(ex);
CompletableFuture<RedisPubSubConnection> result = new CompletableFuture<>();
result.completeExceptionally(ex);
return result;
}
return entry.nextPubSubConnection();
}
private void connect(Codec codec, ChannelName channelName,
MasterSlaveEntry msEntry, RPromise<PubSubConnectionEntry> promise, PubSubType type, AsyncSemaphore lock, RedisPubSubListener<?>... listeners) {
RFuture<RedisPubSubConnection> connFuture = nextPubSubConnection(msEntry, channelName);
promise.onComplete((res, e) -> {
MasterSlaveEntry msEntry, CompletableFuture<PubSubConnectionEntry> promise, PubSubType type, AsyncSemaphore lock, RedisPubSubListener<?>... listeners) {
CompletionStage<RedisPubSubConnection> connFuture = nextPubSubConnection(msEntry, channelName);
promise.whenComplete((res, e) -> {
if (e != null) {
((RPromise<RedisPubSubConnection>) connFuture).tryFailure(e);
}
});
connFuture.onComplete((conn, ex) -> {
connFuture.whenComplete((conn, ex) -> {
if (ex != null) {
lock.release();
promise.tryFailure(ex);
promise.completeExceptionally(ex);
return;
}
@ -380,7 +361,7 @@ public class PublishSubscribeService {
}
freePubSubLock.release();
RFuture<Void> subscribeFuture = addListeners(channelName, promise, type, lock, entry, listeners);
addListeners(channelName, promise, type, lock, entry, listeners);
ChannelFuture future;
if (PubSubType.PSUBSCRIBE == type) {
@ -392,13 +373,13 @@ public class PublishSubscribeService {
future.addListener((ChannelFutureListener) future1 -> {
if (!future1.isSuccess()) {
if (!promise.isDone()) {
subscribeFuture.cancel(false);
promise.cancel(false);
}
return;
}
connectionManager.newTimeout(timeout ->
subscribeFuture.cancel(false),
promise.cancel(false),
config.getTimeout(), TimeUnit.MILLISECONDS);
});
});
@ -611,8 +592,8 @@ public class PublishSubscribeService {
private void subscribe(ChannelName channelName, Collection<RedisPubSubListener<?>> listeners,
Codec subscribeCodec) {
RFuture<PubSubConnectionEntry> subscribeFuture = subscribe(subscribeCodec, channelName, listeners.toArray(new RedisPubSubListener[0]));
subscribeFuture.onComplete((res, e) -> {
CompletableFuture<PubSubConnectionEntry> subscribeFuture = subscribe(subscribeCodec, channelName, listeners.toArray(new RedisPubSubListener[0]));
subscribeFuture.whenComplete((res, e) -> {
if (e != null) {
connectionManager.newTimeout(task -> {
subscribe(channelName, listeners, subscribeCodec);
@ -626,9 +607,9 @@ public class PublishSubscribeService {
private void psubscribe(ChannelName channelName, Collection<RedisPubSubListener<?>> listeners,
Codec subscribeCodec) {
RFuture<Collection<PubSubConnectionEntry>> subscribeFuture =
CompletableFuture<Collection<PubSubConnectionEntry>> subscribeFuture =
psubscribe(channelName, subscribeCodec, listeners.toArray(new RedisPubSubListener[0]));
subscribeFuture.onComplete((res, e) -> {
subscribeFuture.whenComplete((res, e) -> {
if (e != null) {
connectionManager.newTimeout(task -> {
psubscribe(channelName, listeners, subscribeCodec);
@ -640,8 +621,8 @@ public class PublishSubscribeService {
});
}
public RFuture<Void> removeListenerAsync(PubSubType type, ChannelName channelName, EventListener listener) {
RPromise<Void> promise = new RedissonPromise<>();
public CompletableFuture<Void> removeListenerAsync(PubSubType type, ChannelName channelName, EventListener listener) {
CompletableFuture<Void> promise = new CompletableFuture<>();
AsyncSemaphore semaphore = getSemaphore(channelName);
semaphore.acquire(() -> {
Collection<MasterSlaveEntry> entries = Collections.singletonList(getEntry(channelName));
@ -655,7 +636,7 @@ public class PublishSubscribeService {
if (entry == null) {
if (counter.decrementAndGet() == 0) {
semaphore.release();
promise.trySuccess(null);
promise.complete(null);
}
continue;
}
@ -666,13 +647,13 @@ public class PublishSubscribeService {
.onComplete((r, ex) -> {
if (counter.decrementAndGet() == 0) {
semaphore.release();
promise.trySuccess(null);
promise.complete(null);
}
});
} else {
if (counter.decrementAndGet() == 0) {
semaphore.release();
promise.trySuccess(null);
promise.complete(null);
}
}
}
@ -680,8 +661,8 @@ public class PublishSubscribeService {
return promise;
}
public RFuture<Void> removeListenerAsync(PubSubType type, ChannelName channelName, Integer... listenerIds) {
RPromise<Void> promise = new RedissonPromise<>();
public CompletableFuture<Void> removeListenerAsync(PubSubType type, ChannelName channelName, Integer... listenerIds) {
CompletableFuture<Void> promise = new CompletableFuture<>();
AsyncSemaphore semaphore = getSemaphore(channelName);
semaphore.acquire(() -> {
Collection<MasterSlaveEntry> entries = Collections.singletonList(getEntry(channelName));
@ -695,7 +676,7 @@ public class PublishSubscribeService {
if (entry == null) {
if (counter.decrementAndGet() == 0) {
semaphore.release();
promise.trySuccess(null);
promise.complete(null);
}
continue;
}
@ -708,13 +689,13 @@ public class PublishSubscribeService {
.onComplete((r, ex) -> {
if (counter.decrementAndGet() == 0) {
semaphore.release();
promise.trySuccess(null);
promise.complete(null);
}
});
} else {
if (counter.decrementAndGet() == 0) {
semaphore.release();
promise.trySuccess(null);
promise.complete(null);
}
}
}

@ -16,7 +16,8 @@
package org.redisson.pubsub;
import org.redisson.RedissonLockEntry;
import org.redisson.misc.RPromise;
import java.util.concurrent.CompletableFuture;
/**
*
@ -30,7 +31,7 @@ public class SemaphorePubSub extends PublishSubscribe<RedissonLockEntry> {
}
@Override
protected RedissonLockEntry createEntry(RPromise<RedissonLockEntry> newPromise) {
protected RedissonLockEntry createEntry(CompletableFuture<RedissonLockEntry> newPromise) {
return new RedissonLockEntry(newPromise);
}

@ -24,10 +24,10 @@ import org.redisson.command.CommandBatchService;
import org.redisson.connection.ConnectionManager;
import org.redisson.connection.NodeSource;
import org.redisson.liveobject.core.RedissonObjectBuilder;
import org.redisson.misc.RPromise;
import reactor.core.publisher.Mono;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
/**
*
@ -64,14 +64,14 @@ public class CommandReactiveBatchService extends CommandReactiveService {
}
@Override
protected <R> RPromise<R> createPromise() {
protected <R> CompletableFuture<R> createPromise() {
return batchService.createPromise();
}
@Override
public <V, R> void async(boolean readOnlyMode, NodeSource nodeSource,
Codec codec, RedisCommand<V> command, Object[] params, RPromise<R> mainPromise, boolean ignoreRedirect, boolean noRetry) {
batchService.async(readOnlyMode, nodeSource, codec, command, params, mainPromise, ignoreRedirect, noRetry);
public <V, R> RFuture<R> async(boolean readOnlyMode, NodeSource nodeSource,
Codec codec, RedisCommand<V> command, Object[] params, boolean ignoreRedirect, boolean noRetry) {
return batchService.async(readOnlyMode, nodeSource, codec, command, params, ignoreRedirect, noRetry);
}
public RFuture<BatchResult<?>> executeAsync() {

@ -26,9 +26,9 @@ import org.redisson.command.CommandBatchService;
import org.redisson.connection.ConnectionManager;
import org.redisson.connection.NodeSource;
import org.redisson.liveobject.core.RedissonObjectBuilder;
import org.redisson.misc.RPromise;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
/**
*
@ -65,14 +65,14 @@ public class CommandRxBatchService extends CommandRxService {
}
@Override
protected <R> RPromise<R> createPromise() {
protected <R> CompletableFuture<R> createPromise() {
return batchService.createPromise();
}
@Override
public <V, R> void async(boolean readOnlyMode, NodeSource nodeSource,
Codec codec, RedisCommand<V> command, Object[] params, RPromise<R> mainPromise, boolean ignoreRedirect, boolean noRetry) {
batchService.async(readOnlyMode, nodeSource, codec, command, params, mainPromise, ignoreRedirect, noRetry);
public <V, R> RFuture<R> async(boolean readOnlyMode, NodeSource nodeSource,
Codec codec, RedisCommand<V> command, Object[] params, boolean ignoreRedirect, boolean noRetry) {
return batchService.async(readOnlyMode, nodeSource, codec, command, params, ignoreRedirect, noRetry);
}
public RFuture<BatchResult<?>> executeAsync() {

@ -137,7 +137,7 @@ public class RedisClientTest {
CommandData<String, String> cmd4 = conn.create(null, RedisCommands.PING);
commands.add(cmd4);
RPromise<Void> p = new RedissonPromise<Void>();
CompletableFuture<Void> p = new CompletableFuture<Void>();
conn.send(new CommandsData(p, commands, false, false));
assertThat(cmd1.getPromise().get()).isEqualTo("PONG");
@ -172,7 +172,7 @@ public class RedisClientTest {
commands.add(cmd1);
}
RPromise<Void> p = new RedissonPromise<Void>();
CompletableFuture<Void> p = new CompletableFuture<Void>();
conn.send(new CommandsData(p, commands, false, false));
for (CommandData<?, ?> commandData : commands) {

@ -422,7 +422,7 @@ public class RedissonBatchTest extends BaseTest {
for (int i = 0; i < total; i++) {
RFuture<String> f = map.putAsync("" + i, "" + i, 5, TimeUnit.MINUTES);
if (batchOptions.getExecutionMode() == ExecutionMode.REDIS_WRITE_ATOMIC) {
((BatchPromise)f).getSentPromise().toCompletableFuture().join();
((BatchPromise)f.toCompletableFuture()).getSentPromise().join();
}
}

Loading…
Cancel
Save