All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.redisson.spring.data.connection.RedissonReactiveScriptingCommands Maven / Gradle / Ivy

There is a newer version: 3.39.0
Show newest version
/**
 * 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.spring.data.connection;

import org.redisson.api.RFuture;
import org.redisson.client.codec.ByteArrayCodec;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.client.protocol.RedisCommands;
import org.redisson.misc.CompletableFutureWrapper;
import org.redisson.reactive.CommandReactiveExecutor;
import org.springframework.data.redis.connection.ReactiveScriptingCommands;
import org.springframework.data.redis.connection.ReturnType;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 
 * @author Nikita Koksharov
 *
 */
public class RedissonReactiveScriptingCommands extends RedissonBaseReactive implements ReactiveScriptingCommands {

    RedissonReactiveScriptingCommands(CommandReactiveExecutor executorService) {
        super(executorService);
    }

    @Override
    public Mono scriptFlush() {
        return executorService.reactive(() -> {
            RFuture f = executorService.writeAllVoidAsync(RedisCommands.SCRIPT_FLUSH);
            return toStringFuture(f);
        });
    }

    @Override
    public Mono scriptKill() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Mono scriptLoad(ByteBuffer script) {
        return executorService.reactive(() -> {
            List> futures = executorService.executeAllAsync(RedisCommands.SCRIPT_LOAD, toByteArray(script));
            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 Flux scriptExists(List scriptShas) {
        Mono> m = executorService.reactive(() -> {
            List>> futures = executorService.writeAllAsync(RedisCommands.SCRIPT_EXISTS, scriptShas.toArray());
            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);
        });
        return m.flatMapMany(v -> Flux.fromIterable(v));
    }

    protected RedisCommand toCommand(ReturnType returnType, String name) {
        RedisCommand c = null; 
        if (returnType == ReturnType.BOOLEAN) {
            c = org.redisson.api.RScript.ReturnType.BOOLEAN.getCommand();
        } else if (returnType == ReturnType.INTEGER) {
            c = org.redisson.api.RScript.ReturnType.INTEGER.getCommand();
        } else if (returnType == ReturnType.MULTI) {
            c = org.redisson.api.RScript.ReturnType.MULTI.getCommand();
            return new RedisCommand(c, name, new BinaryConvertor());
        } else if (returnType == ReturnType.STATUS) {
            c = org.redisson.api.RScript.ReturnType.STATUS.getCommand();
        } else if (returnType == ReturnType.VALUE) {
            c = org.redisson.api.RScript.ReturnType.VALUE.getCommand();
            return new RedisCommand(c, name, new BinaryConvertor());
        }
        return new RedisCommand(c, name);
    }
    
    @Override
    public  Flux eval(ByteBuffer script, ReturnType returnType, int numKeys, ByteBuffer... keysAndArgs) {
        RedisCommand c = toCommand(returnType, "EVAL");
        List params = new ArrayList();
        params.add(toByteArray(script));
        params.add(numKeys);
        params.addAll(Arrays.stream(keysAndArgs).map(m -> toByteArray(m)).collect(Collectors.toList()));
        Mono m = write(null, ByteArrayCodec.INSTANCE, c, params.toArray());
        return convert(m);
    }

    protected  Flux convert(Mono m) {
        return (Flux) m.map(e -> {
            if (e.getClass().isArray()) {
                return ByteBuffer.wrap((byte[])e);
            }
            if (e instanceof List) {
                List l = (List) e;
                if (!l.isEmpty()) {
                    for (int i = 0; i < l.size(); i++) {
                        if (l.get(i).getClass().isArray()) {
                            l.set(i, ByteBuffer.wrap((byte[])l.get(i)));
                        }
                    }
                    return l;
                }
            }
            return e;
        }).flux();
    }

    @Override
    public  Flux evalSha(String scriptSha, ReturnType returnType, int numKeys, ByteBuffer... keysAndArgs) {
        RedisCommand c = toCommand(returnType, "EVALSHA");
        List params = new ArrayList();
        params.add(scriptSha);
        params.add(numKeys);
        params.addAll(Arrays.stream(keysAndArgs).map(m -> toByteArray(m)).collect(Collectors.toList()));
        Mono m = write(null, ByteArrayCodec.INSTANCE, c, params.toArray());
        return convert(m);
    }

}