|
|
|
@ -47,9 +47,47 @@ import reactor.core.publisher.Mono;
|
|
|
|
|
*/
|
|
|
|
|
public class RedissonReactiveSubscription implements ReactiveSubscription {
|
|
|
|
|
|
|
|
|
|
public static class ListenableCounter {
|
|
|
|
|
|
|
|
|
|
private int state;
|
|
|
|
|
private Runnable r;
|
|
|
|
|
|
|
|
|
|
public synchronized void acquire() {
|
|
|
|
|
state++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void release() {
|
|
|
|
|
synchronized (this) {
|
|
|
|
|
state--;
|
|
|
|
|
if (state != 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r != null) {
|
|
|
|
|
r.run();
|
|
|
|
|
r = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized void addListener(Runnable r) {
|
|
|
|
|
synchronized (this) {
|
|
|
|
|
if (state != 0) {
|
|
|
|
|
this.r = r;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r.run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private final Map<ByteBuffer, PubSubConnectionEntry> channels = new ConcurrentHashMap<ByteBuffer, PubSubConnectionEntry>();
|
|
|
|
|
private final Map<ByteBuffer, PubSubConnectionEntry> patterns = new ConcurrentHashMap<ByteBuffer, PubSubConnectionEntry>();
|
|
|
|
|
|
|
|
|
|
private final ListenableCounter monosListener = new ListenableCounter();
|
|
|
|
|
|
|
|
|
|
private final PublishSubscribeService subscribeService;
|
|
|
|
|
|
|
|
|
|
public RedissonReactiveSubscription(ConnectionManager connectionManager) {
|
|
|
|
@ -58,14 +96,21 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Mono<Void> subscribe(ByteBuffer... channels) {
|
|
|
|
|
monosListener.acquire();
|
|
|
|
|
return Mono.defer(() -> {
|
|
|
|
|
RedissonPromise<Void> result = new RedissonPromise<Void>();
|
|
|
|
|
result.onComplete((r, ex) -> {
|
|
|
|
|
monosListener.release();
|
|
|
|
|
});
|
|
|
|
|
CountableListener<Void> listener = new CountableListener<Void>(result, null, channels.length);
|
|
|
|
|
for (ByteBuffer channel : channels) {
|
|
|
|
|
RFuture<PubSubConnectionEntry> f = subscribeService.subscribe(ByteArrayCodec.INSTANCE, toChannelName(channel));
|
|
|
|
|
f.onComplete((res, e) -> RedissonReactiveSubscription.this.channels.put(channel, res));
|
|
|
|
|
f.onComplete(listener);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Mono.fromFuture(result);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected ChannelName toChannelName(ByteBuffer channel) {
|
|
|
|
@ -74,7 +119,12 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Mono<Void> pSubscribe(ByteBuffer... patterns) {
|
|
|
|
|
monosListener.acquire();
|
|
|
|
|
return Mono.defer(() -> {
|
|
|
|
|
RedissonPromise<Void> result = new RedissonPromise<Void>();
|
|
|
|
|
result.onComplete((r, ex) -> {
|
|
|
|
|
monosListener.release();
|
|
|
|
|
});
|
|
|
|
|
CountableListener<Void> listener = new CountableListener<Void>(result, null, patterns.length);
|
|
|
|
|
for (ByteBuffer channel : patterns) {
|
|
|
|
|
RFuture<PubSubConnectionEntry> f = subscribeService.psubscribe(toChannelName(channel), ByteArrayCodec.INSTANCE);
|
|
|
|
@ -82,6 +132,7 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
|
|
|
|
|
f.onComplete(listener);
|
|
|
|
|
}
|
|
|
|
|
return Mono.fromFuture(result);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -91,13 +142,28 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Mono<Void> unsubscribe(ByteBuffer... channels) {
|
|
|
|
|
monosListener.acquire();
|
|
|
|
|
return Mono.defer(() -> {
|
|
|
|
|
RedissonPromise<Void> result = new RedissonPromise<Void>();
|
|
|
|
|
result.onComplete((r, ex) -> {
|
|
|
|
|
monosListener.release();
|
|
|
|
|
});
|
|
|
|
|
CountableListener<Void> listener = new CountableListener<Void>(result, null, channels.length);
|
|
|
|
|
for (ByteBuffer channel : channels) {
|
|
|
|
|
RFuture<Codec> f = subscribeService.unsubscribe(toChannelName(channel), PubSubType.UNSUBSCRIBE);
|
|
|
|
|
ChannelName cn = toChannelName(channel);
|
|
|
|
|
RFuture<Codec> f = subscribeService.unsubscribe(cn, PubSubType.UNSUBSCRIBE);
|
|
|
|
|
f.onComplete((res, e) -> {
|
|
|
|
|
synchronized (RedissonReactiveSubscription.this.channels) {
|
|
|
|
|
PubSubConnectionEntry entry = RedissonReactiveSubscription.this.channels.get(channel);
|
|
|
|
|
if (!entry.hasListeners(cn)) {
|
|
|
|
|
RedissonReactiveSubscription.this.channels.remove(channel);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
f.onComplete(listener);
|
|
|
|
|
}
|
|
|
|
|
return Mono.fromFuture(result);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -107,13 +173,28 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Mono<Void> pUnsubscribe(ByteBuffer... patterns) {
|
|
|
|
|
monosListener.acquire();
|
|
|
|
|
return Mono.defer(() -> {
|
|
|
|
|
RedissonPromise<Void> result = new RedissonPromise<Void>();
|
|
|
|
|
result.onComplete((r, ex) -> {
|
|
|
|
|
monosListener.release();
|
|
|
|
|
});
|
|
|
|
|
CountableListener<Void> listener = new CountableListener<Void>(result, null, patterns.length);
|
|
|
|
|
for (ByteBuffer channel : patterns) {
|
|
|
|
|
RFuture<Codec> f = subscribeService.unsubscribe(toChannelName(channel), PubSubType.PUNSUBSCRIBE);
|
|
|
|
|
ChannelName cn = toChannelName(channel);
|
|
|
|
|
RFuture<Codec> f = subscribeService.unsubscribe(cn, PubSubType.PUNSUBSCRIBE);
|
|
|
|
|
f.onComplete((res, e) -> {
|
|
|
|
|
synchronized (RedissonReactiveSubscription.this.patterns) {
|
|
|
|
|
PubSubConnectionEntry entry = RedissonReactiveSubscription.this.patterns.get(channel);
|
|
|
|
|
if (!entry.hasListeners(cn)) {
|
|
|
|
|
RedissonReactiveSubscription.this.patterns.remove(channel);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
f.onComplete(listener);
|
|
|
|
|
}
|
|
|
|
|
return Mono.fromFuture(result);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -138,6 +219,7 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
|
|
|
|
|
Flux<Message<ByteBuffer, ByteBuffer>> f = Flux.<Message<ByteBuffer, ByteBuffer>>create(emitter -> {
|
|
|
|
|
emitter.onRequest(n -> {
|
|
|
|
|
|
|
|
|
|
monosListener.addListener(() -> {
|
|
|
|
|
AtomicLong counter = new AtomicLong(n);
|
|
|
|
|
BaseRedisPubSubListener listener = new BaseRedisPubSubListener() {
|
|
|
|
|
@Override
|
|
|
|
@ -182,6 +264,7 @@ public class RedissonReactiveSubscription implements ReactiveSubscription {
|
|
|
|
|
emitter.onDispose(disposable);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (flux.compareAndSet(null, f)) {
|
|
|
|
|
return f;
|
|
|
|
|