org.redisson.RedissonBaseAdder Maven / Gradle / Ivy
/**
* Copyright 2018 Nikita Koksharov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.redisson;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.redisson.api.RFuture;
import org.redisson.api.RSemaphore;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.api.listener.MessageListener;
import org.redisson.client.ChannelName;
import org.redisson.client.codec.LongCodec;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonPromise;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;
/**
*
* @author Nikita Koksharov
*
*/
public abstract class RedissonBaseAdder extends RedissonExpirable {
private class ResetListener implements FutureListener {
private final RPromise result;
private ResetListener(RPromise result) {
this.result = result;
}
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
result.tryFailure(future.cause());
return;
}
acquireAsync(future.getNow().intValue()).addListener(new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
result.tryFailure(future.cause());
return;
}
result.trySuccess(null);
}
});
}
protected RFuture acquireAsync(int value) {
return semaphore.acquireAsync(value);
}
}
private class SumListener implements FutureListener {
private final RPromise result;
private SumListener(RPromise result) {
this.result = result;
}
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
result.tryFailure(future.cause());
return;
}
acquireAsync(future.getNow().intValue()).addListener(new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
result.tryFailure(future.cause());
return;
}
RFuture valueFuture = getAndDeleteAsync();
valueFuture.addListener(new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
result.tryFailure(future.cause());
return;
}
result.trySuccess(future.getNow());
}
});
}
});
}
protected RFuture acquireAsync(int value) {
return semaphore.acquireAsync(value);
}
}
private static final Logger log = LoggerFactory.getLogger(RedissonBaseAdder.class);
private static final long CLEAR_MSG = 0;
private static final long SUM_MSG = 1;
private final RSemaphore semaphore;
private final RTopic topic;
private final int listenerId;
public RedissonBaseAdder(CommandAsyncExecutor connectionManager, String name, RedissonClient redisson) {
super(connectionManager, name);
topic = redisson.getTopic(suffixName(getName(), "topic"), LongCodec.INSTANCE);
semaphore = redisson.getSemaphore(suffixName(getName(), "semaphore"));
listenerId = topic.addListener(Long.class, new MessageListener() {
@Override
public void onMessage(CharSequence channel, Long msg) {
if (msg == SUM_MSG) {
RFuture addAndGetFuture = addAndGetAsync();
addAndGetFuture.addListener(new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
log.error("Can't increase sum", future.cause());
return;
}
semaphore.releaseAsync().addListener(new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
log.error("Can't release semaphore", future.cause());
return;
}
}
});
}
});
}
if (msg == CLEAR_MSG) {
doReset();
semaphore.releaseAsync().addListener(new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
log.error("Can't release semaphore", future.cause());
return;
}
}
});
}
}
});
}
protected abstract void doReset();
public void reset() {
get(resetAsync());
}
public void reset(long timeout, TimeUnit timeUnit) {
get(resetAsync(timeout, timeUnit));
}
public RFuture sumAsync() {
final RPromise result = new RedissonPromise();
RFuture future = topic.publishAsync(SUM_MSG);
future.addListener(new SumListener(result));
return result;
}
public RFuture sumAsync(final long timeout, final TimeUnit timeUnit) {
RPromise result = new RedissonPromise();
RFuture future = topic.publishAsync(SUM_MSG);
future.addListener(new SumListener(result) {
@Override
protected RFuture acquireAsync(int value) {
return tryAcquire(timeout, timeUnit, value);
}
});
return result;
}
protected RFuture tryAcquire(long timeout, TimeUnit timeUnit, int value) {
final RPromise acquireResult = new RedissonPromise();
semaphore.tryAcquireAsync(value, timeout, timeUnit).addListener(new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
acquireResult.tryFailure(future.cause());
return;
}
if (future.getNow()) {
acquireResult.trySuccess(null);
} else {
acquireResult.tryFailure(new TimeoutException());
}
}
});
return acquireResult;
}
public RFuture resetAsync() {
final RPromise result = new RedissonPromise();
RFuture future = topic.publishAsync(CLEAR_MSG);
future.addListener(new ResetListener(result));
return result;
}
public RFuture resetAsync(final long timeout, final TimeUnit timeUnit) {
final RPromise result = new RedissonPromise();
RFuture future = topic.publishAsync(CLEAR_MSG);
future.addListener(new ResetListener(result) {
@Override
protected RFuture acquireAsync(int value) {
return tryAcquire(timeout, timeUnit, value);
}
});
return result;
}
public void destroy() {
topic.removeListener(listenerId);
}
protected abstract RFuture addAndGetAsync();
protected abstract RFuture getAndDeleteAsync();
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy