Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.redisson.RedissonScript Maven / Gradle / Ivy
Go to download
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;
import org.redisson.api.RFuture;
import org.redisson.api.RScript;
import org.redisson.client.codec.Codec;
import org.redisson.client.codec.StringCodec;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.client.protocol.RedisCommands;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.misc.CompletableFutureWrapper;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
*
* @author Nikita Koksharov
*
*/
public class RedissonScript implements RScript {
private final Codec codec;
private final CommandAsyncExecutor commandExecutor;
public RedissonScript(CommandAsyncExecutor commandExecutor) {
this.commandExecutor = commandExecutor;
this.codec = commandExecutor.getServiceManager().getCfg().getCodec();
}
public RedissonScript(CommandAsyncExecutor commandExecutor, Codec codec) {
this.commandExecutor = commandExecutor;
this.codec = commandExecutor.getServiceManager().getCodec(codec);
}
@Override
public String scriptLoad(String luaScript) {
return commandExecutor.get(scriptLoadAsync(luaScript));
}
public String scriptLoad(String key, String luaScript) {
return commandExecutor.get(scriptLoadAsync(key, luaScript));
}
@Override
public RFuture scriptLoadAsync(String luaScript) {
List> futures = commandExecutor.executeAllAsync(RedisCommands.SCRIPT_LOAD, luaScript);
CompletableFuture f = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
CompletableFuture s = f.thenApply(r -> futures.get(0).getNow(null));
return new CompletableFutureWrapper<>(s);
}
@Override
public RFuture scriptLoadAsync(String key, String luaScript) {
return commandExecutor.writeAsync(key, StringCodec.INSTANCE, RedisCommands.SCRIPT_LOAD, luaScript);
}
@Override
public R eval(Mode mode, String luaScript, ReturnType returnType) {
return eval(mode, luaScript, returnType, Collections.emptyList());
}
@Override
public R eval(Mode mode, String luaScript, ReturnType returnType, List keys, Object... values) {
String key = getKey(keys);
return eval(key, mode, luaScript, returnType, keys, values);
}
private static String getKey(List keys) {
String key = null;
if (!keys.isEmpty()) {
if (keys.get(0) instanceof byte[]) {
key = new String((byte[]) keys.get(0));
} else {
key = keys.get(0).toString();
}
}
return key;
}
@Override
public RFuture evalAsync(Mode mode, String luaScript, ReturnType returnType, List keys, Object... values) {
String key = getKey(keys);
return evalAsync(key, mode, luaScript, returnType, keys, values);
}
@Override
public R evalSha(Mode mode, String shaDigest, ReturnType returnType) {
return evalSha(null, mode, shaDigest, returnType, Collections.emptyList());
}
@Override
public R evalSha(Mode mode, String shaDigest, ReturnType returnType, List keys, Object... values) {
return evalSha(null, mode, shaDigest, returnType, keys, values);
}
@Override
public RFuture evalShaAsync(Mode mode, String shaDigest, ReturnType returnType, List keys, Object... values) {
return evalShaAsync(null, mode, codec, shaDigest, returnType, keys, values);
}
public RFuture evalShaAsync(String key, Mode mode, Codec codec, String shaDigest, ReturnType returnType, List keys, Object... values) {
RedissonScript script = new RedissonScript(commandExecutor, codec);
return script.evalShaAsync(key, mode, shaDigest, returnType, keys, values);
}
@Override
public void scriptKill() {
commandExecutor.get(scriptKillAsync());
}
public void scriptKill(String key) {
commandExecutor.get(scriptKillAsync(key));
}
@Override
public RFuture scriptKillAsync() {
return commandExecutor.writeAllVoidAsync(RedisCommands.SCRIPT_KILL);
}
public RFuture scriptKillAsync(String key) {
return commandExecutor.writeAsync(key, RedisCommands.SCRIPT_KILL);
}
@Override
public List scriptExists(String... shaDigests) {
return commandExecutor.get(scriptExistsAsync(shaDigests));
}
@Override
public RFuture> scriptExistsAsync(String... shaDigests) {
List>> futures = commandExecutor.executeAllAsync(RedisCommands.SCRIPT_EXISTS, (Object[]) shaDigests);
CompletableFuture f = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
CompletableFuture> s = f.thenApply(r -> {
List result = futures.get(0).getNow(new ArrayList<>());
for (CompletableFuture> future : futures.subList(1, futures.size())) {
List l = future.getNow(new ArrayList<>());
for (int i = 0; i < l.size(); i++) {
result.set(i, result.get(i) | l.get(i));
}
}
return result;
});
return new CompletableFutureWrapper<>(s);
}
public List scriptExists(String key, String... shaDigests) {
return commandExecutor.get(scriptExistsAsync(key, shaDigests));
}
public RFuture> scriptExistsAsync(String key, String... shaDigests) {
return commandExecutor.writeAsync(key, RedisCommands.SCRIPT_EXISTS, shaDigests);
}
@Override
public void scriptFlush() {
commandExecutor.get(scriptFlushAsync());
}
public void scriptFlush(String key) {
commandExecutor.get(scriptFlushAsync(key));
}
@Override
public RFuture scriptFlushAsync() {
return commandExecutor.writeAllVoidAsync(RedisCommands.SCRIPT_FLUSH);
}
public RFuture scriptFlushAsync(String key) {
return commandExecutor.writeAsync(key, RedisCommands.SCRIPT_FLUSH);
}
@Override
public RFuture evalShaAsync(Mode mode, String shaDigest, ReturnType returnType) {
return evalShaAsync(null, mode, codec, shaDigest, returnType, Collections.emptyList());
}
@Override
public RFuture evalAsync(Mode mode, String luaScript, ReturnType returnType) {
return evalAsync(null, mode, luaScript, returnType, Collections.emptyList());
}
private List encode(Collection> values, Codec codec) {
List result = new ArrayList(values.size());
for (Object object : values) {
result.add(commandExecutor.encode(codec, object));
}
return result;
}
@Override
public RFuture evalShaAsync(String key, Mode mode, String shaDigest, ReturnType returnType,
List keys, Object... values) {
RedisCommand command = new RedisCommand(returnType.getCommand(), "EVALSHA");
String mappedKey = commandExecutor.getServiceManager().getConfig().getNameMapper().map(key);
List mappedKeys = keys.stream()
.map(k -> {
if (k instanceof String) {
return commandExecutor.getServiceManager().getConfig().getNameMapper().map(k.toString());
}
return k;
})
.collect(Collectors.toList());
if (mode == Mode.READ_ONLY && commandExecutor.isEvalShaROSupported()) {
RedisCommand cmd = new RedisCommand(returnType.getCommand(), "EVALSHA_RO");
RFuture f = commandExecutor.evalReadAsync(mappedKey, codec, cmd, shaDigest, mappedKeys, encode(Arrays.asList(values), codec).toArray());
CompletableFuture result = new CompletableFuture<>();
f.whenComplete((r, e) -> {
if (e != null && e.getMessage().startsWith("ERR unknown command")) {
commandExecutor.setEvalShaROSupported(false);
RFuture s = evalShaAsync(mappedKey, mode, shaDigest, returnType, mappedKeys, values);
commandExecutor.transfer(s.toCompletableFuture(), result);
return;
}
commandExecutor.transfer(f.toCompletableFuture(), result);
});
return new CompletableFutureWrapper<>(result);
}
return commandExecutor.evalWriteAsync(mappedKey, codec, command, shaDigest, mappedKeys, encode(Arrays.asList(values), codec).toArray());
}
@Override
public RFuture evalAsync(String key, Mode mode, String luaScript, ReturnType returnType, List keys,
Object... values) {
String mappedKey = commandExecutor.getServiceManager().getConfig().getNameMapper().map(key);
List mappedKeys = keys.stream()
.map(k -> {
if (k instanceof String) {
return commandExecutor.getServiceManager().getConfig().getNameMapper().map(k.toString());
}
return k;
})
.collect(Collectors.toList());
if (mode == Mode.READ_ONLY) {
return commandExecutor.evalReadAsync(mappedKey, codec, returnType.getCommand(), luaScript, mappedKeys, encode(Arrays.asList(values), codec).toArray());
}
return commandExecutor.evalWriteAsync(mappedKey, codec, returnType.getCommand(), luaScript, mappedKeys, encode(Arrays.asList(values), codec).toArray());
}
@Override
public R evalSha(String key, Mode mode, String shaDigest, ReturnType returnType, List keys,
Object... values) {
return commandExecutor.get(evalShaAsync(key, mode, shaDigest, returnType, keys, values));
}
@Override
public R eval(String key, Mode mode, String luaScript, ReturnType returnType, List keys,
Object... values) {
return commandExecutor.get(evalAsync(key, mode, luaScript, returnType, keys, values));
}
@Override
public R eval(Mode mode, String luaScript, ReturnType returnType, Function, R> resultMapper, Object... values) {
return commandExecutor.get(evalAsync(mode, luaScript, returnType, resultMapper, values));
}
@Override
public RFuture evalAsync(Mode mode, String luaScript, ReturnType returnType, Function, R> resultMapper, Object... values) {
List args = new ArrayList<>();
args.add(luaScript);
args.add(0);
for (Object object : values) {
args.add(commandExecutor.encode(codec, object));
}
List> futures;
if (mode == Mode.READ_ONLY) {
futures = commandExecutor.readAllAsync(codec, returnType.getCommand(), args.toArray());
} else {
futures = commandExecutor.writeAllAsync(codec, returnType.getCommand(), args.toArray());
}
CompletableFuture r = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
CompletableFuture res = r.thenApply(v -> {
List l = futures.stream().map(f -> f.join()).collect(Collectors.toList());
return resultMapper.apply(l);
});
return new CompletableFutureWrapper<>(res);
}
@Override
public R evalSha(Mode mode, String shaDigest, ReturnType returnType, Function, R> resultMapper, Object... values) {
return commandExecutor.get(evalShaAsync(mode, shaDigest, returnType, resultMapper, values));
}
@Override
public RFuture evalShaAsync(Mode mode, String shaDigest, ReturnType returnType, Function, R> resultMapper, Object... values) {
List args = new ArrayList<>();
args.add(shaDigest);
args.add(0);
for (Object object : values) {
args.add(commandExecutor.encode(codec, object));
}
if (mode == Mode.READ_ONLY && commandExecutor.isEvalShaROSupported()) {
RedisCommand cmd = new RedisCommand(returnType.getCommand(), "EVALSHA_RO");
List> futures = commandExecutor.readAllAsync(codec, cmd, args.toArray());
CompletableFuture r = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
CompletableFuture rr = r.handle((res, e) -> {
if (e != null) {
if (e.getMessage().startsWith("ERR unknown command")) {
commandExecutor.setEvalShaROSupported(false);
return evalShaAsync(mode, shaDigest, returnType, resultMapper, values);
}
CompletableFuture ex = new CompletableFuture<>();
ex.completeExceptionally(e);
return ex;
}
List l = futures.stream().map(f -> f.join()).collect(Collectors.toList());
R result = resultMapper.apply(l);
return CompletableFuture.completedFuture(result);
}).thenCompose(ff -> ff);
return new CompletableFutureWrapper<>(rr);
}
List> futures = commandExecutor.readAllAsync(codec, returnType.getCommand(), args.toArray());
CompletableFuture r = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
CompletableFuture res = r.thenApply(v -> {
List l = futures.stream().map(f -> f.join()).collect(Collectors.toList());
return resultMapper.apply(l);
});
return new CompletableFutureWrapper<>(res);
}
}