org.redisson.remote.BaseRemoteService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of redisson-all Show documentation
Show all versions of redisson-all Show documentation
Easy Redis Java client and Real-Time Data Platform. Valkey compatible. Sync/Async/RxJava3/Reactive API. Client side caching. Over 50 Redis based Java objects and services: JCache API, Apache Tomcat, Hibernate, Spring, Set, Multimap, SortedSet, Map, List, Queue, Deque, Semaphore, Lock, AtomicLong, Map Reduce, Bloom filter, Scheduler, RPC
/**
* Copyright (c) 2013-2024 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.remote;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import org.redisson.RedissonBlockingQueue;
import org.redisson.RedissonMap;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RFuture;
import org.redisson.api.RMap;
import org.redisson.api.RemoteInvocationOptions;
import org.redisson.api.annotation.RRemoteAsync;
import org.redisson.api.annotation.RRemoteReactive;
import org.redisson.api.annotation.RRemoteRx;
import org.redisson.client.codec.Codec;
import org.redisson.client.codec.StringCodec;
import org.redisson.codec.CompositeCodec;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.executor.RemotePromise;
import org.redisson.misc.Hash;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
*
* @author Nikita Koksharov
*
*/
public abstract class BaseRemoteService {
private final Map, String> requestQueueNameCache = new ConcurrentHashMap<>();
private final ConcurrentMap methodSignaturesCache = new ConcurrentHashMap<>();
protected final Codec codec;
protected final String name;
protected final CommandAsyncExecutor commandExecutor;
protected final String executorId;
protected final String cancelRequestMapName;
protected final String cancelResponseMapName;
protected final String responseQueueName;
public BaseRemoteService(Codec codec, String name, CommandAsyncExecutor commandExecutor, String executorId) {
this.codec = commandExecutor.getServiceManager().getCodec(codec);
this.name = commandExecutor.getServiceManager().getConfig().getNameMapper().map(name);
this.commandExecutor = commandExecutor;
this.executorId = executorId;
this.cancelRequestMapName = "{" + name + ":remote" + "}:cancel-request";
this.cancelResponseMapName = "{" + name + ":remote" + "}:cancel-response";
this.responseQueueName = getResponseQueueName(executorId);
}
public String getResponseQueueName(String executorId) {
return "{remote_response}:" + executorId;
}
protected String getAckName(String requestId) {
return "{" + name + ":remote" + "}:" + requestId + ":ack";
}
public String getRequestQueueName(Class> remoteInterface) {
return requestQueueNameCache.computeIfAbsent(remoteInterface, k -> "{" + name + ":" + k.getName() + "}");
}
protected ByteBuf encode(Object obj) {
try {
return codec.getValueEncoder().encode(obj);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
public T get(Class remoteInterface) {
return get(remoteInterface, RemoteInvocationOptions.defaults());
}
public T get(Class remoteInterface, long executionTimeout, TimeUnit executionTimeUnit) {
return get(remoteInterface,
RemoteInvocationOptions.defaults().expectResultWithin(executionTimeout, executionTimeUnit));
}
public T get(Class remoteInterface, long executionTimeout, TimeUnit executionTimeUnit, long ackTimeout,
TimeUnit ackTimeUnit) {
return get(remoteInterface, RemoteInvocationOptions.defaults().expectAckWithin(ackTimeout, ackTimeUnit)
.expectResultWithin(executionTimeout, executionTimeUnit));
}
public T get(Class remoteInterface, RemoteInvocationOptions options) {
for (Annotation annotation : remoteInterface.getAnnotations()) {
if (annotation.annotationType() == RRemoteAsync.class) {
Class syncInterface = (Class) ((RRemoteAsync) annotation).value();
AsyncRemoteProxy proxy = new AsyncRemoteProxy(commandExecutor, name, responseQueueName,
codec, executorId, cancelRequestMapName, this);
return proxy.create(remoteInterface, options, syncInterface);
}
if (annotation.annotationType() == RRemoteReactive.class) {
Class syncInterface = (Class) ((RRemoteReactive) annotation).value();
ReactiveRemoteProxy proxy = new ReactiveRemoteProxy(commandExecutor, name, responseQueueName,
codec, executorId, cancelRequestMapName, this);
return proxy.create(remoteInterface, options, syncInterface);
}
if (annotation.annotationType() == RRemoteRx.class) {
Class syncInterface = (Class) ((RRemoteRx) annotation).value();
RxRemoteProxy proxy = new RxRemoteProxy(commandExecutor, name, responseQueueName,
codec, executorId, cancelRequestMapName, this);
return proxy.create(remoteInterface, options, syncInterface);
}
}
SyncRemoteProxy proxy = new SyncRemoteProxy(commandExecutor, name, responseQueueName, codec, executorId, this);
return proxy.create(remoteInterface, options);
}
protected long getTimeout(Long executionTimeoutInMillis, RemoteServiceRequest request) {
return executionTimeoutInMillis;
}
protected RMap getMap(String name) {
return new RedissonMap<>(new CompositeCodec(StringCodec.INSTANCE, codec, codec), commandExecutor, name);
}
protected void scheduleCheck(String mapName, String requestId, CompletableFuture cancelRequest) {
commandExecutor.getServiceManager().newTimeout(new TimerTask() {
@Override
public void run(Timeout timeout) throws Exception {
if (cancelRequest.isDone()) {
return;
}
RMap canceledRequests = getMap(mapName);
RFuture future = canceledRequests.removeAsync(requestId);
future.whenComplete((request, ex) -> {
if (cancelRequest.isDone()) {
return;
}
if (ex != null) {
scheduleCheck(mapName, requestId, cancelRequest);
return;
}
if (request == null) {
scheduleCheck(mapName, requestId, cancelRequest);
} else {
cancelRequest.complete(request);
}
});
}
}, 3000, TimeUnit.MILLISECONDS);
}
protected String generateRequestId(Object[] args) {
return commandExecutor.getServiceManager().generateId();
}
protected abstract CompletableFuture addAsync(String requestQueueName, RemoteServiceRequest request,
RemotePromise
© 2015 - 2024 Weber Informatics LLC | Privacy Policy