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

io.lettuce.core.AbstractRedisReactiveCommands Maven / Gradle / Ivy

Go to download

Advanced and thread-safe Java Redis client for synchronous, asynchronous, and reactive usage. Supports Cluster, Sentinel, Pipelining, Auto-Reconnect, Codecs and much more.

The newest version!
/*
 * Copyright 2011-Present, Redis Ltd. and Contributors
 * All rights reserved.
 *
 * Licensed under the MIT License.
 *
 * This file contains contributions from third-party contributors
 * 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
 *
 *      https://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 io.lettuce.core;

import io.lettuce.core.GeoArgs.Unit;
import io.lettuce.core.api.StatefulConnection;
import io.lettuce.core.api.reactive.*;
import io.lettuce.core.cluster.api.reactive.RedisClusterReactiveCommands;
import io.lettuce.core.codec.Base16;
import io.lettuce.core.codec.RedisCodec;
import io.lettuce.core.internal.LettuceAssert;
import io.lettuce.core.json.JsonParser;
import io.lettuce.core.json.JsonPath;
import io.lettuce.core.json.JsonType;
import io.lettuce.core.json.JsonValue;
import io.lettuce.core.json.arguments.JsonGetArgs;
import io.lettuce.core.json.arguments.JsonMsetArgs;
import io.lettuce.core.json.arguments.JsonRangeArgs;
import io.lettuce.core.json.arguments.JsonSetArgs;
import io.lettuce.core.models.stream.ClaimedMessages;
import io.lettuce.core.models.stream.PendingMessage;
import io.lettuce.core.models.stream.PendingMessages;
import io.lettuce.core.output.CommandOutput;
import io.lettuce.core.output.KeyStreamingChannel;
import io.lettuce.core.output.KeyValueStreamingChannel;
import io.lettuce.core.output.ScoredValueStreamingChannel;
import io.lettuce.core.output.ValueStreamingChannel;
import io.lettuce.core.protocol.Command;
import io.lettuce.core.protocol.CommandArgs;
import io.lettuce.core.protocol.CommandType;
import io.lettuce.core.protocol.ProtocolKeyword;
import io.lettuce.core.protocol.RedisCommand;
import io.lettuce.core.protocol.TracedCommand;
import io.lettuce.core.resource.ClientResources;
import io.lettuce.core.tracing.TraceContext;
import io.lettuce.core.tracing.TraceContextProvider;
import io.lettuce.core.tracing.Tracing;
import io.netty.util.concurrent.EventExecutorGroup;
import io.netty.util.concurrent.ImmediateEventExecutor;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;

import static io.lettuce.core.protocol.CommandType.EXEC;
import static io.lettuce.core.protocol.CommandType.GEORADIUSBYMEMBER_RO;
import static io.lettuce.core.protocol.CommandType.GEORADIUS_RO;

/**
 * A reactive and thread-safe API for a Redis connection.
 *
 * @param  Key type.
 * @param  Value type.
 * @author Mark Paluch
 * @author Nikolai Perevozchikov
 * @author Tugdual Grall
 * @author dengliming
 * @author Andrey Shlykov
 * @author Ali Takavci
 * @author Tihomir Mateev
 * @since 4.0
 */
public abstract class AbstractRedisReactiveCommands
        implements RedisAclReactiveCommands, RedisHashReactiveCommands, RedisKeyReactiveCommands,
        RedisStringReactiveCommands, RedisListReactiveCommands, RedisSetReactiveCommands,
        RedisSortedSetReactiveCommands, RedisScriptingReactiveCommands, RedisServerReactiveCommands,
        RedisHLLReactiveCommands, BaseRedisReactiveCommands, RedisTransactionalReactiveCommands,
        RedisGeoReactiveCommands, RedisClusterReactiveCommands, RedisJsonReactiveCommands {

    private final StatefulConnection connection;

    private final RedisCommandBuilder commandBuilder;

    private final RedisJsonCommandBuilder jsonCommandBuilder;

    private final Mono parser;

    private final ClientResources clientResources;

    private final boolean tracingEnabled;

    private volatile EventExecutorGroup scheduler;

    /**
     * Initialize a new instance.
     *
     * @param connection the connection to operate on.
     * @param codec the codec for command encoding.
     */
    public AbstractRedisReactiveCommands(StatefulConnection connection, RedisCodec codec, Mono parser) {
        this.connection = connection;
        this.parser = parser;
        this.commandBuilder = new RedisCommandBuilder<>(codec);
        this.jsonCommandBuilder = new RedisJsonCommandBuilder<>(codec, parser);
        this.clientResources = connection.getResources();
        this.tracingEnabled = clientResources.tracing().isEnabled();
    }

    private EventExecutorGroup getScheduler() {

        EventExecutorGroup scheduler = this.scheduler;
        if (scheduler != null) {
            return scheduler;
        }

        EventExecutorGroup schedulerToUse = ImmediateEventExecutor.INSTANCE;

        if (connection.getOptions().isPublishOnScheduler()) {
            schedulerToUse = connection.getResources().eventExecutorGroup();
        }

        return this.scheduler = schedulerToUse;
    }

    @Override
    public JsonParser getJsonParser() {
        return parser.block();
    }

    @Override
    public Mono> aclCat() {
        return createMono(commandBuilder::aclCat);
    }

    @Override
    public Mono> aclCat(AclCategory category) {
        return createMono(() -> commandBuilder.aclCat(category));
    }

    @Override
    public Mono aclDeluser(String... usernames) {
        return createMono(() -> commandBuilder.aclDeluser(usernames));
    }

    @Override
    public Mono aclDryRun(String username, String command, String... args) {
        return createMono(() -> commandBuilder.aclDryRun(username, command, args));
    }

    @Override
    public Mono aclDryRun(String username, RedisCommand command) {
        return createMono(() -> commandBuilder.aclDryRun(username, command));
    }

    @Override
    public Mono aclGenpass() {
        return createMono(commandBuilder::aclGenpass);
    }

    @Override
    public Mono aclGenpass(int bits) {
        return createMono(() -> commandBuilder.aclGenpass(bits));
    }

    @Override
    public Mono> aclGetuser(String username) {
        return createMono(() -> commandBuilder.aclGetuser(username));
    }

    @Override
    public Flux aclList() {
        return createDissolvingFlux(commandBuilder::aclList);
    }

    @Override
    public Mono aclLoad() {
        return createMono(commandBuilder::aclLoad);
    }

    @Override
    public Flux> aclLog() {
        return createDissolvingFlux(commandBuilder::aclLog);
    }

    @Override
    public Flux> aclLog(int count) {
        return createDissolvingFlux(() -> commandBuilder.aclLog(count));
    }

    @Override
    public Mono aclLogReset() {
        return createMono(commandBuilder::aclLogReset);
    }

    @Override
    public Mono aclSave() {
        return createMono(commandBuilder::aclSave);
    }

    @Override
    public Mono aclSetuser(String username, AclSetuserArgs args) {
        return createMono(() -> commandBuilder.aclSetuser(username, args));
    }

    @Override
    public Flux aclUsers() {
        return createDissolvingFlux(commandBuilder::aclUsers);
    }

    @Override
    public Mono aclWhoami() {
        return createMono(commandBuilder::aclWhoami);
    }

    @Override
    public Mono append(K key, V value) {
        return createMono(() -> commandBuilder.append(key, value));
    }

    @Override
    public Mono asking() {
        return createMono(commandBuilder::asking);
    }

    @Override
    public Mono auth(CharSequence password) {
        return createMono(() -> commandBuilder.auth(password));
    }

    @Override
    public Mono auth(String username, CharSequence password) {
        return createMono(() -> commandBuilder.auth(username, password));
    }

    @Override
    public Mono bgrewriteaof() {
        return createMono(commandBuilder::bgrewriteaof);
    }

    @Override
    public Mono bgsave() {
        return createMono(commandBuilder::bgsave);
    }

    @Override
    public Mono bitcount(K key) {
        return createMono(() -> commandBuilder.bitcount(key));
    }

    @Override
    public Mono bitcount(K key, long start, long end) {
        return createMono(() -> commandBuilder.bitcount(key, start, end));
    }

    @Override
    public Flux> bitfield(K key, BitFieldArgs args) {
        return createDissolvingFlux(() -> commandBuilder.bitfieldValue(key, args));
    }

    @Override
    public Mono bitopAnd(K destination, K... keys) {
        return createMono(() -> commandBuilder.bitopAnd(destination, keys));
    }

    @Override
    public Mono bitopNot(K destination, K source) {
        return createMono(() -> commandBuilder.bitopNot(destination, source));
    }

    @Override
    public Mono bitopOr(K destination, K... keys) {
        return createMono(() -> commandBuilder.bitopOr(destination, keys));
    }

    @Override
    public Mono bitopXor(K destination, K... keys) {
        return createMono(() -> commandBuilder.bitopXor(destination, keys));
    }

    @Override
    public Mono bitpos(K key, boolean state) {
        return createMono(() -> commandBuilder.bitpos(key, state));
    }

    @Override
    public Mono bitpos(K key, boolean state, long start) {
        return createMono(() -> commandBuilder.bitpos(key, state, start));
    }

    @Override
    public Mono bitpos(K key, boolean state, long start, long end) {
        return createMono(() -> commandBuilder.bitpos(key, state, start, end));
    }

    @Override
    public Mono blmove(K source, K destination, LMoveArgs args, long timeout) {
        return createMono(() -> commandBuilder.blmove(source, destination, args, timeout));
    }

    @Override
    public Mono blmove(K source, K destination, LMoveArgs args, double timeout) {
        return createMono(() -> commandBuilder.blmove(source, destination, args, timeout));
    }

    @Override
    public Mono>> blmpop(long timeout, LMPopArgs args, K... keys) {
        return createMono(() -> commandBuilder.blmpop(timeout, args, keys));
    }

    @Override
    public Mono>> blmpop(double timeout, LMPopArgs args, K... keys) {
        return createMono(() -> commandBuilder.blmpop(timeout, args, keys));
    }

    @Override
    public Mono> blpop(long timeout, K... keys) {
        return createMono(() -> commandBuilder.blpop(timeout, keys));
    }

    @Override
    public Mono> blpop(double timeout, K... keys) {
        return createMono(() -> commandBuilder.blpop(timeout, keys));
    }

    @Override
    public Mono> brpop(long timeout, K... keys) {
        return createMono(() -> commandBuilder.brpop(timeout, keys));
    }

    @Override
    public Mono> brpop(double timeout, K... keys) {
        return createMono(() -> commandBuilder.brpop(timeout, keys));
    }

    @Override
    public Mono brpoplpush(long timeout, K source, K destination) {
        return createMono(() -> commandBuilder.brpoplpush(timeout, source, destination));
    }

    @Override
    public Mono brpoplpush(double timeout, K source, K destination) {
        return createMono(() -> commandBuilder.brpoplpush(timeout, source, destination));
    }

    @Override
    public Mono clientCaching(boolean enabled) {
        return createMono(() -> commandBuilder.clientCaching(enabled));
    }

    @Override
    public Mono clientGetname() {
        return createMono(commandBuilder::clientGetname);
    }

    @Override
    public Mono clientGetredir() {
        return createMono(commandBuilder::clientGetredir);
    }

    @Override
    public Mono clientKill(String addr) {
        return createMono(() -> commandBuilder.clientKill(addr));
    }

    @Override
    public Mono clientKill(KillArgs killArgs) {
        return createMono(() -> commandBuilder.clientKill(killArgs));
    }

    @Override
    public Mono clientList() {
        return createMono(commandBuilder::clientList);
    }

    @Override
    public Mono clientList(ClientListArgs clientListArgs) {
        return createMono(() -> commandBuilder.clientList(clientListArgs));
    }

    @Override
    public Mono clientInfo() {
        return createMono(commandBuilder::clientInfo);
    }

    @Override
    public Mono clientNoEvict(boolean on) {
        return createMono(() -> commandBuilder.clientNoEvict(on));
    }

    @Override
    public Mono clientId() {
        return createMono(commandBuilder::clientId);
    }

    @Override
    public Mono clientPause(long timeout) {
        return createMono(() -> commandBuilder.clientPause(timeout));
    }

    @Override
    public Mono clientSetname(K name) {
        return createMono(() -> commandBuilder.clientSetname(name));
    }

    @Override
    public Mono clientSetinfo(String key, String value) {
        return createMono(() -> commandBuilder.clientSetinfo(key, value));
    }

    @Override
    public Mono clientTracking(TrackingArgs args) {
        return createMono(() -> commandBuilder.clientTracking(args));
    }

    @Override
    public Mono clientTrackinginfo() {
        return createMono(commandBuilder::clientTrackinginfo);
    }

    @Override
    public Mono clientUnblock(long id, UnblockType type) {
        return createMono(() -> commandBuilder.clientUnblock(id, type));
    }

    public void close() {
        connection.close();
    }

    @Override
    public Mono clusterAddSlots(int... slots) {
        return createMono(() -> commandBuilder.clusterAddslots(slots));
    }

    @Override
    public Mono clusterAddSlotsRange(Range... ranges) {
        return createMono(() -> commandBuilder.clusterAddSlotsRange(ranges));
    }

    @Override
    public Mono clusterBumpepoch() {
        return createMono(() -> commandBuilder.clusterBumpepoch());
    }

    @Override
    public Mono clusterCountFailureReports(String nodeId) {
        return createMono(() -> commandBuilder.clusterCountFailureReports(nodeId));
    }

    @Override
    public Mono clusterCountKeysInSlot(int slot) {
        return createMono(() -> commandBuilder.clusterCountKeysInSlot(slot));
    }

    @Override
    public Mono clusterDelSlots(int... slots) {
        return createMono(() -> commandBuilder.clusterDelslots(slots));
    }

    @Override
    public Mono clusterDelSlotsRange(Range... ranges) {
        return createMono(() -> commandBuilder.clusterDelSlotsRange(ranges));
    }

    @Override
    public Mono clusterFailover(boolean force) {
        return createMono(() -> commandBuilder.clusterFailover(force));
    }

    @Override
    public Mono clusterFailover(boolean force, boolean takeOver) {
        return createMono(() -> commandBuilder.clusterFailover(force, takeOver));
    }

    @Override
    public Mono clusterFlushslots() {
        return createMono(commandBuilder::clusterFlushslots);
    }

    @Override
    public Mono clusterForget(String nodeId) {
        return createMono(() -> commandBuilder.clusterForget(nodeId));
    }

    @Override
    public Flux clusterGetKeysInSlot(int slot, int count) {
        return createDissolvingFlux(() -> commandBuilder.clusterGetKeysInSlot(slot, count));
    }

    @Override
    public Mono clusterInfo() {
        return createMono(commandBuilder::clusterInfo);
    }

    @Override
    public Mono clusterKeyslot(K key) {
        return createMono(() -> commandBuilder.clusterKeyslot(key));
    }

    @Override
    public Mono clusterMeet(String ip, int port) {
        return createMono(() -> commandBuilder.clusterMeet(ip, port));
    }

    @Override
    public Mono clusterMyId() {
        return createMono(commandBuilder::clusterMyId);
    }

    @Override
    public Mono clusterMyShardId() {
        return createMono(commandBuilder::clusterMyShardId);
    }

    @Override
    public Mono clusterNodes() {
        return createMono(commandBuilder::clusterNodes);
    }

    @Override
    public Mono clusterReplicate(String nodeId) {
        return createMono(() -> commandBuilder.clusterReplicate(nodeId));
    }

    @Override
    public Flux clusterReplicas(String nodeId) {
        return createDissolvingFlux(() -> commandBuilder.clusterReplicas(nodeId));
    }

    @Override
    public Mono clusterReset(boolean hard) {
        return createMono(() -> commandBuilder.clusterReset(hard));
    }

    @Override
    public Mono clusterSaveconfig() {
        return createMono(() -> commandBuilder.clusterSaveconfig());
    }

    @Override
    public Mono clusterSetConfigEpoch(long configEpoch) {
        return createMono(() -> commandBuilder.clusterSetConfigEpoch(configEpoch));
    }

    @Override
    public Mono clusterSetSlotImporting(int slot, String nodeId) {
        return createMono(() -> commandBuilder.clusterSetSlotImporting(slot, nodeId));
    }

    @Override
    public Mono clusterSetSlotMigrating(int slot, String nodeId) {
        return createMono(() -> commandBuilder.clusterSetSlotMigrating(slot, nodeId));
    }

    @Override
    public Mono clusterSetSlotNode(int slot, String nodeId) {
        return createMono(() -> commandBuilder.clusterSetSlotNode(slot, nodeId));
    }

    @Override
    public Mono clusterSetSlotStable(int slot) {
        return createMono(() -> commandBuilder.clusterSetSlotStable(slot));
    }

    @Override
    public Mono> clusterShards() {
        return createMono(() -> commandBuilder.clusterShards());
    }

    @Override
    public Flux clusterSlaves(String nodeId) {
        return createDissolvingFlux(() -> commandBuilder.clusterSlaves(nodeId));
    }

    @Override
    public Flux clusterSlots() {
        return createDissolvingFlux(commandBuilder::clusterSlots);
    }

    @Override
    public Flux command() {
        return createDissolvingFlux(commandBuilder::command);
    }

    @Override
    public Mono commandCount() {
        return createMono(commandBuilder::commandCount);
    }

    @Override
    public Flux commandInfo(String... commands) {
        return createDissolvingFlux(() -> commandBuilder.commandInfo(commands));
    }

    @Override
    public Flux commandInfo(CommandType... commands) {
        String[] stringCommands = new String[commands.length];
        for (int i = 0; i < commands.length; i++) {
            stringCommands[i] = commands[i].name();
        }

        return commandInfo(stringCommands);
    }

    @Override
    public Mono> configGet(String parameter) {
        return createMono(() -> commandBuilder.configGet(parameter));
    }

    @Override
    public Mono> configGet(String... parameters) {
        return createMono(() -> commandBuilder.configGet(parameters));
    }

    @Override
    public Mono configResetstat() {
        return createMono(commandBuilder::configResetstat);
    }

    @Override
    public Mono configRewrite() {
        return createMono(commandBuilder::configRewrite);
    }

    @Override
    public Mono configSet(String parameter, String value) {
        return createMono(() -> commandBuilder.configSet(parameter, value));
    }

    @Override
    public Mono configSet(Map kvs) {
        return createMono(() -> commandBuilder.configSet(kvs));
    }

    @SuppressWarnings("unchecked")
    public  Flux createDissolvingFlux(Supplier> commandSupplier) {
        return (Flux) createFlux(commandSupplier, true);
    }

    public  Flux createFlux(Supplier> commandSupplier) {
        return createFlux(commandSupplier, false);
    }

    private  Flux createFlux(Supplier> commandSupplier, boolean dissolve) {

        if (tracingEnabled) {

            return withTraceContext().flatMapMany(it -> Flux
                    .from(new RedisPublisher<>(decorate(commandSupplier, it), connection, dissolve, getScheduler().next())));
        }

        return Flux.from(new RedisPublisher<>(commandSupplier, connection, dissolve, getScheduler().next()));
    }

    private Mono withTraceContext() {

        return Tracing.getContext()
                .switchIfEmpty(Mono.fromSupplier(() -> clientResources.tracing().initialTraceContextProvider()))
                .flatMap(TraceContextProvider::getTraceContextLater).defaultIfEmpty(TraceContext.EMPTY);
    }

    protected  Mono createMono(CommandType type, CommandOutput output, CommandArgs args) {
        return createMono(() -> new Command<>(type, output, args));
    }

    public  Mono createMono(Supplier> commandSupplier) {

        if (tracingEnabled) {

            return withTraceContext().flatMap(it -> Mono
                    .from(new RedisPublisher<>(decorate(commandSupplier, it), connection, false, getScheduler().next())));
        }

        return Mono.from(new RedisPublisher<>(commandSupplier, connection, false, getScheduler().next()));
    }

    private  Supplier> decorate(Supplier> commandSupplier,
            TraceContext traceContext) {
        return () -> new TracedCommand<>(commandSupplier.get(), traceContext);
    }

    @Override
    public Mono dbsize() {
        return createMono(commandBuilder::dbsize);
    }

    @Override
    public Mono debugCrashAndRecover(Long delay) {
        return createMono(() -> (commandBuilder.debugCrashAndRecover(delay)));
    }

    @Override
    public Mono debugHtstats(int db) {
        return createMono(() -> commandBuilder.debugHtstats(db));
    }

    @Override
    public Mono debugObject(K key) {
        return createMono(() -> commandBuilder.debugObject(key));
    }

    @Override
    public Mono debugOom() {
        return createMono(commandBuilder::debugOom).then();
    }

    @Override
    public Mono debugReload() {
        return createMono(() -> (commandBuilder.debugReload()));
    }

    @Override
    public Mono debugRestart(Long delay) {
        return createMono(() -> (commandBuilder.debugRestart(delay)));
    }

    @Override
    public Mono debugSdslen(K key) {
        return createMono(() -> (commandBuilder.debugSdslen(key)));
    }

    @Override
    public Mono debugSegfault() {
        return createFlux(commandBuilder::debugSegfault).then();
    }

    @Override
    public Mono decr(K key) {
        return createMono(() -> commandBuilder.decr(key));
    }

    @Override
    public Mono decrby(K key, long amount) {
        return createMono(() -> commandBuilder.decrby(key, amount));
    }

    @Override
    public Mono del(K... keys) {
        return createMono(() -> commandBuilder.del(keys));
    }

    public Mono del(Iterable keys) {
        return createMono(() -> commandBuilder.del(keys));
    }

    @Override
    public String digest(String script) {
        return digest(encodeScript(script));
    }

    @Override
    public String digest(byte[] script) {
        return Base16.digest(script);
    }

    @Override
    public Mono discard() {
        return createMono(commandBuilder::discard);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public  Flux dispatch(ProtocolKeyword type, CommandOutput output) {

        LettuceAssert.notNull(type, "Command type must not be null");
        LettuceAssert.notNull(output, "CommandOutput type must not be null");

        return (Flux) createFlux(() -> new Command<>(type, output));
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public  Flux dispatch(ProtocolKeyword type, CommandOutput output, CommandArgs args) {

        LettuceAssert.notNull(type, "Command type must not be null");
        LettuceAssert.notNull(output, "CommandOutput type must not be null");
        LettuceAssert.notNull(args, "CommandArgs type must not be null");

        return (Flux) createFlux(() -> new Command<>(type, output, args));
    }

    @Override
    public Mono dump(K key) {
        return createMono(() -> commandBuilder.dump(key));
    }

    @Override
    public Mono echo(V msg) {
        return createMono(() -> commandBuilder.echo(msg));
    }

    @Override
    @SuppressWarnings("unchecked")
    public  Flux eval(String script, ScriptOutputType type, K... keys) {
        return eval(encodeScript(script), type, keys);
    }

    @Override
    @SuppressWarnings("unchecked")
    public  Flux eval(byte[] script, ScriptOutputType type, K... keys) {
        return createFlux(() -> commandBuilder.eval(script, type, keys));
    }

    @Override
    @SuppressWarnings("unchecked")
    public  Flux eval(String script, ScriptOutputType type, K[] keys, V... values) {
        return eval(encodeScript(script), type, keys, values);
    }

    @Override
    @SuppressWarnings("unchecked")
    public  Flux eval(byte[] script, ScriptOutputType type, K[] keys, V... values) {
        return createFlux(() -> commandBuilder.eval(script, type, keys, values));
    }

    @Override
    @SuppressWarnings("unchecked")
    public  Flux evalReadOnly(String script, ScriptOutputType type, K[] keys, V... values) {
        return evalReadOnly(encodeScript(script), type, keys, values);
    }

    @Override
    public  Flux evalReadOnly(byte[] script, ScriptOutputType type, K[] keys, V... values) {
        return createFlux(() -> commandBuilder.eval(script, type, true, keys, values));
    }

    @Override
    @SuppressWarnings("unchecked")
    public  Flux evalsha(String digest, ScriptOutputType type, K... keys) {
        return createFlux(() -> commandBuilder.evalsha(digest, type, keys));
    }

    @Override
    @SuppressWarnings("unchecked")
    public  Flux evalsha(String digest, ScriptOutputType type, K[] keys, V... values) {
        return createFlux(() -> commandBuilder.evalsha(digest, type, keys, values));
    }

    @Override
    public  Flux evalshaReadOnly(String digest, ScriptOutputType type, K[] keys, V... values) {
        return createFlux(() -> commandBuilder.evalsha(digest, type, true, keys, values));
    }

    @Override
    public Mono exec() {
        return createMono(EXEC, null, null);
    }

    public Mono exists(K key) {
        return createMono(() -> commandBuilder.exists(key));
    }

    @Override
    public Mono exists(K... keys) {
        return createMono(() -> commandBuilder.exists(keys));
    }

    public Mono exists(Iterable keys) {
        return createMono(() -> commandBuilder.exists(keys));
    }

    @Override
    public Mono expire(K key, long seconds) {
        return expire(key, seconds, null);
    }

    @Override
    public Mono expire(K key, long seconds, ExpireArgs expireArgs) {
        return createMono(() -> commandBuilder.expire(key, seconds, expireArgs));
    }

    @Override
    public Mono expire(K key, Duration seconds) {
        return expire(key, seconds, null);
    }

    @Override
    public Mono expire(K key, Duration seconds, ExpireArgs expireArgs) {
        LettuceAssert.notNull(seconds, "Timeout must not be null");
        return expire(key, seconds.toMillis() / 1000, expireArgs);
    }

    @Override
    public Flux hexpire(K key, long seconds, K... fields) {
        return hexpire(key, seconds, null, fields);
    }

    @Override
    public Flux hexpire(K key, long seconds, ExpireArgs expireArgs, K... fields) {
        return createDissolvingFlux(() -> commandBuilder.hexpire(key, seconds, expireArgs, fields));
    }

    @Override
    public Flux hexpire(K key, Duration seconds, K... fields) {
        return hexpire(key, seconds, null, fields);
    }

    @Override
    public Flux hexpire(K key, Duration seconds, ExpireArgs expireArgs, K... fields) {
        LettuceAssert.notNull(seconds, "Timeout must not be null");
        return hexpire(key, seconds.toMillis() / 1000, expireArgs, fields);
    }

    @Override
    public Mono expireat(K key, long timestamp) {
        return expireat(key, timestamp, null);
    }

    @Override
    public Mono expireat(K key, long timestamp, ExpireArgs expireArgs) {
        return createMono(() -> commandBuilder.expireat(key, timestamp, expireArgs));
    }

    @Override
    public Mono expireat(K key, Date timestamp) {
        return expireat(key, timestamp, null);
    }

    @Override
    public Mono expireat(K key, Date timestamp, ExpireArgs expireArgs) {
        LettuceAssert.notNull(timestamp, "Timestamp must not be null");
        return expireat(key, timestamp.getTime() / 1000, expireArgs);
    }

    @Override
    public Mono expireat(K key, Instant timestamp) {
        return expireat(key, timestamp, null);
    }

    @Override
    public Mono expireat(K key, Instant timestamp, ExpireArgs expireArgs) {
        LettuceAssert.notNull(timestamp, "Timestamp must not be null");
        return expireat(key, timestamp.toEpochMilli() / 1000, expireArgs);
    }

    @Override
    public Flux hexpireat(K key, long timestamp, K... fields) {
        return hexpireat(key, timestamp, null, fields);
    }

    @Override
    public Flux hexpireat(K key, long timestamp, ExpireArgs expireArgs, K... fields) {
        return createDissolvingFlux(() -> commandBuilder.hexpireat(key, timestamp, expireArgs, fields));
    }

    @Override
    public Flux hexpireat(K key, Date timestamp, K... fields) {
        return hexpireat(key, timestamp, null, fields);
    }

    @Override
    public Flux hexpireat(K key, Date timestamp, ExpireArgs expireArgs, K... fields) {
        LettuceAssert.notNull(timestamp, "Timestamp must not be null");
        return hexpireat(key, timestamp.getTime() / 1000, expireArgs, fields);
    }

    @Override
    public Flux hexpireat(K key, Instant timestamp, K... fields) {
        return hexpireat(key, timestamp, null, fields);
    }

    @Override
    public Flux hexpireat(K key, Instant timestamp, ExpireArgs expireArgs, K... fields) {
        LettuceAssert.notNull(timestamp, "Timestamp must not be null");
        return hexpireat(key, timestamp.toEpochMilli() / 1000, expireArgs, fields);
    }

    @Override
    public Mono expiretime(K key) {
        return createMono(() -> commandBuilder.expiretime(key));
    }

    @Override
    public Flux hexpiretime(K key, K... fields) {
        return createDissolvingFlux(() -> commandBuilder.hexpiretime(key, fields));
    }

    @Override
    public Flux httl(K key, K... fields) {
        return createDissolvingFlux(() -> commandBuilder.httl(key, fields));
    }

    @Override
    public Flux hpexpire(K key, long milliseconds, K... fields) {
        return hpexpire(key, milliseconds, null, fields);
    }

    @Override
    public Flux hpexpire(K key, long milliseconds, ExpireArgs expireArgs, K... fields) {
        return createDissolvingFlux(() -> commandBuilder.hpexpire(key, milliseconds, expireArgs, fields));
    }

    @Override
    public Flux hpexpire(K key, Duration milliseconds, K... fields) {
        return hpexpire(key, milliseconds, null, fields);
    }

    @Override
    public Flux hpexpire(K key, Duration milliseconds, ExpireArgs expireArgs, K... fields) {
        LettuceAssert.notNull(milliseconds, "Timeout must not be null");
        return hpexpire(key, milliseconds.toMillis(), expireArgs, fields);
    }

    @Override
    public Flux hpexpireat(K key, Date timestamp, K... fields) {
        return hpexpireat(key, timestamp, null, fields);
    }

    @Override
    public Flux hpexpireat(K key, Date timestamp, ExpireArgs expireArgs, K... fields) {
        LettuceAssert.notNull(timestamp, "Timestamp must not be null");
        return hpexpireat(key, timestamp.getTime(), expireArgs, fields);
    }

    @Override
    public Flux hpexpireat(K key, Instant timestamp, K... fields) {
        return hpexpireat(key, timestamp, null, fields);
    }

    @Override
    public Flux hpexpireat(K key, Instant timestamp, ExpireArgs expireArgs, K... fields) {
        LettuceAssert.notNull(timestamp, "Timestamp must not be null");
        return hpexpireat(key, timestamp.toEpochMilli(), expireArgs, fields);
    }

    @Override
    public Flux hpexpireat(K key, long timestamp, K... fields) {
        return hpexpireat(key, timestamp, null, fields);
    }

    @Override
    public Flux hpexpireat(K key, long timestamp, ExpireArgs expireArgs, K... fields) {
        return createDissolvingFlux(() -> commandBuilder.hpexpireat(key, timestamp, expireArgs, fields));
    }

    @Override
    public Flux hpexpiretime(K key, K... fields) {
        return createDissolvingFlux(() -> commandBuilder.hpexpiretime(key, fields));
    }

    @Override
    public Flux hpttl(K key, K... fields) {
        return createDissolvingFlux(() -> commandBuilder.hpttl(key, fields));
    }

    @Override
    public  Flux fcall(String function, ScriptOutputType type, K... keys) {
        return createFlux(() -> commandBuilder.fcall(function, type, false, keys));
    }

    @Override
    public  Flux fcall(String function, ScriptOutputType type, K[] keys, V... values) {
        return createFlux(() -> commandBuilder.fcall(function, type, false, keys, values));
    }

    @Override
    public  Flux fcallReadOnly(String function, ScriptOutputType type, K... keys) {
        return createFlux(() -> commandBuilder.fcall(function, type, true, keys));
    }

    @Override
    public  Flux fcallReadOnly(String function, ScriptOutputType type, K[] keys, V... values) {
        return createFlux(() -> commandBuilder.fcall(function, type, true, keys, values));
    }

    @Override
    public Mono functionLoad(String functionCode) {
        return functionLoad(functionCode, false);
    }

    @Override
    public Mono functionLoad(String functionCode, boolean replace) {
        return createMono(() -> commandBuilder.functionLoad(encodeScript(functionCode), replace));
    }

    @Override
    public Mono functionDump() {
        return createMono(commandBuilder::functionDump);
    }

    @Override
    public Mono functionRestore(byte[] dump) {
        return createMono(() -> commandBuilder.functionRestore(dump, null));
    }

    @Override
    public Mono functionRestore(byte[] dump, FunctionRestoreMode mode) {
        return createMono(() -> commandBuilder.functionRestore(dump, mode));
    }

    @Override
    public Mono functionFlush(FlushMode flushMode) {
        return createMono(() -> commandBuilder.functionFlush(flushMode));
    }

    @Override
    public Mono functionKill() {
        return createMono(commandBuilder::functionKill);
    }

    @Override
    public Flux> functionList() {
        return createDissolvingFlux(() -> commandBuilder.functionList(null));
    }

    @Override
    public Flux> functionList(String libraryName) {
        return createDissolvingFlux(() -> commandBuilder.functionList(libraryName));
    }

    @Override
    public void flushCommands() {
        connection.flushCommands();
    }

    @Override
    public Mono flushall() {
        return createMono(commandBuilder::flushall);
    }

    @Override
    public Mono flushall(FlushMode flushMode) {
        return createMono(() -> commandBuilder.flushall(flushMode));
    }

    @Override
    public Mono flushallAsync() {
        return flushall(FlushMode.ASYNC);
    }

    @Override
    public Mono flushdb() {
        return createMono(commandBuilder::flushdb);
    }

    @Override
    public Mono flushdb(FlushMode flushMode) {
        return createMono(() -> commandBuilder.flushdb(flushMode));
    }

    @Override
    public Mono flushdbAsync() {
        return flushdb(FlushMode.ASYNC);
    }

    @Override
    public Mono geoadd(K key, double longitude, double latitude, V member) {
        return geoadd(key, longitude, latitude, member, null);
    }

    @Override
    public Mono geoadd(K key, double longitude, double latitude, V member, GeoAddArgs args) {
        return createMono(() -> commandBuilder.geoadd(key, longitude, latitude, member, args));
    }

    @Override
    public Mono geoadd(K key, Object... lngLatMember) {
        return createMono(() -> commandBuilder.geoadd(key, lngLatMember, null));
    }

    @Override
    public Mono geoadd(K key, GeoValue... values) {
        return createMono(() -> commandBuilder.geoadd(key, values, null));
    }

    @Override
    public Mono geoadd(K key, GeoAddArgs args, Object... lngLatMember) {
        return createMono(() -> commandBuilder.geoadd(key, lngLatMember, args));
    }

    @Override
    public Mono geoadd(K key, GeoAddArgs args, GeoValue... values) {
        return createMono(() -> commandBuilder.geoadd(key, values, args));
    }

    @Override
    public Mono geodist(K key, V from, V to, Unit unit) {
        return createMono(() -> commandBuilder.geodist(key, from, to, unit));
    }

    @Override
    public Flux> geohash(K key, V... members) {
        return createDissolvingFlux(() -> commandBuilder.geohash(key, members));
    }

    @Override
    public Flux> geopos(K key, V... members) {
        return createDissolvingFlux(() -> commandBuilder.geoposValues(key, members));
    }

    @Override
    public Flux georadius(K key, double longitude, double latitude, double distance, GeoArgs.Unit unit) {
        return georadius_ro(key, longitude, latitude, distance, unit);
    }

    @Override
    public Flux> georadius(K key, double longitude, double latitude, double distance, GeoArgs.Unit unit,
            GeoArgs geoArgs) {
        return georadius_ro(key, longitude, latitude, distance, unit, geoArgs);
    }

    @Override
    public Mono georadius(K key, double longitude, double latitude, double distance, Unit unit,
            GeoRadiusStoreArgs geoRadiusStoreArgs) {
        return createMono(() -> commandBuilder.georadius(key, longitude, latitude, distance, unit.name(), geoRadiusStoreArgs));
    }

    protected Flux georadius_ro(K key, double longitude, double latitude, double distance, Unit unit) {
        return createDissolvingFlux(
                () -> commandBuilder.georadius(GEORADIUS_RO, key, longitude, latitude, distance, unit.name()));
    }

    protected Flux> georadius_ro(K key, double longitude, double latitude, double distance, Unit unit,
            GeoArgs geoArgs) {
        return createDissolvingFlux(
                () -> commandBuilder.georadius(GEORADIUS_RO, key, longitude, latitude, distance, unit.name(), geoArgs));
    }

    @Override
    public Flux georadiusbymember(K key, V member, double distance, GeoArgs.Unit unit) {
        return georadiusbymember_ro(key, member, distance, unit);
    }

    @Override
    public Flux> georadiusbymember(K key, V member, double distance, GeoArgs.Unit unit, GeoArgs geoArgs) {
        return georadiusbymember_ro(key, member, distance, unit, geoArgs);
    }

    @Override
    public Mono georadiusbymember(K key, V member, double distance, Unit unit, GeoRadiusStoreArgs geoRadiusStoreArgs) {
        return createMono(() -> commandBuilder.georadiusbymember(key, member, distance, unit.name(), geoRadiusStoreArgs));
    }

    protected Flux georadiusbymember_ro(K key, V member, double distance, Unit unit) {
        return createDissolvingFlux(
                () -> commandBuilder.georadiusbymember(GEORADIUSBYMEMBER_RO, key, member, distance, unit.name()));
    }

    protected Flux> georadiusbymember_ro(K key, V member, double distance, Unit unit, GeoArgs geoArgs) {
        return createDissolvingFlux(
                () -> commandBuilder.georadiusbymember(GEORADIUSBYMEMBER_RO, key, member, distance, unit.name(), geoArgs));
    }

    @Override
    public Flux geosearch(K key, GeoSearch.GeoRef reference, GeoSearch.GeoPredicate predicate) {
        return createDissolvingFlux(() -> commandBuilder.geosearch(key, reference, predicate));
    }

    @Override
    public Flux> geosearch(K key, GeoSearch.GeoRef reference, GeoSearch.GeoPredicate predicate,
            GeoArgs geoArgs) {
        return createDissolvingFlux(() -> commandBuilder.geosearch(key, reference, predicate, geoArgs));
    }

    @Override
    public Mono geosearchstore(K destination, K key, GeoSearch.GeoRef reference, GeoSearch.GeoPredicate predicate,
            GeoArgs geoArgs, boolean storeDist) {
        return createMono(() -> commandBuilder.geosearchstore(destination, key, reference, predicate, geoArgs, storeDist));
    }

    @Override
    public Mono get(K key) {
        return createMono(() -> commandBuilder.get(key));
    }

    public StatefulConnection getConnection() {
        return connection;
    }

    @Override
    public Mono getbit(K key, long offset) {
        return createMono(() -> commandBuilder.getbit(key, offset));
    }

    @Override
    public Mono getdel(K key) {
        return createMono(() -> commandBuilder.getdel(key));
    }

    @Override
    public Mono getex(K key, GetExArgs args) {
        return createMono(() -> commandBuilder.getex(key, args));
    }

    @Override
    public Mono getrange(K key, long start, long end) {
        return createMono(() -> commandBuilder.getrange(key, start, end));
    }

    @Override
    public Mono getset(K key, V value) {
        return createMono(() -> commandBuilder.getset(key, value));
    }

    @Override
    public Mono hdel(K key, K... fields) {
        return createMono(() -> commandBuilder.hdel(key, fields));
    }

    @Override
    public Mono hexists(K key, K field) {
        return createMono(() -> commandBuilder.hexists(key, field));
    }

    @Override
    public Mono hget(K key, K field) {
        return createMono(() -> commandBuilder.hget(key, field));
    }

    @Override
    public Flux> hgetall(K key) {
        return createDissolvingFlux(() -> commandBuilder.hgetallKeyValue(key));
    }

    @Override
    public Mono hgetall(KeyValueStreamingChannel channel, K key) {
        return createMono(() -> commandBuilder.hgetall(channel, key));
    }

    @Override
    public Mono hincrby(K key, K field, long amount) {
        return createMono(() -> commandBuilder.hincrby(key, field, amount));
    }

    @Override
    public Mono hincrbyfloat(K key, K field, double amount) {
        return createMono(() -> commandBuilder.hincrbyfloat(key, field, amount));
    }

    @Override
    public Flux hkeys(K key) {
        return createDissolvingFlux(() -> commandBuilder.hkeys(key));
    }

    @Override
    public Mono hkeys(KeyStreamingChannel channel, K key) {
        return createMono(() -> commandBuilder.hkeys(channel, key));
    }

    @Override
    public Mono hlen(K key) {
        return createMono(() -> commandBuilder.hlen(key));
    }

    @Override
    public Flux> hmget(K key, K... fields) {
        return createDissolvingFlux(() -> commandBuilder.hmgetKeyValue(key, fields));
    }

    @Override
    public Mono hmget(KeyValueStreamingChannel channel, K key, K... fields) {
        return createMono(() -> commandBuilder.hmget(channel, key, fields));
    }

    @Override
    public Mono hrandfield(K key) {
        return createMono(() -> commandBuilder.hrandfield(key));
    }

    @Override
    public Flux hrandfield(K key, long count) {
        return createDissolvingFlux(() -> commandBuilder.hrandfield(key, count));
    }

    @Override
    public Mono> hrandfieldWithvalues(K key) {
        return createMono(() -> commandBuilder.hrandfieldWithvalues(key));
    }

    @Override
    public Flux> hrandfieldWithvalues(K key, long count) {
        return createDissolvingFlux(() -> commandBuilder.hrandfieldWithvalues(key, count));
    }

    @Override
    public Mono hmset(K key, Map map) {
        return createMono(() -> commandBuilder.hmset(key, map));
    }

    @Override
    public Mono> hscan(K key) {
        return createMono(() -> commandBuilder.hscan(key));
    }

    @Override
    public Mono> hscanNovalues(K key) {
        return createMono(() -> commandBuilder.hscanNovalues(key));
    }

    @Override
    public Mono> hscan(K key, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.hscan(key, scanArgs));
    }

    @Override
    public Mono> hscanNovalues(K key, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.hscanNovalues(key, scanArgs));
    }

    @Override
    public Mono> hscan(K key, ScanCursor scanCursor, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.hscan(key, scanCursor, scanArgs));
    }

    @Override
    public Mono> hscanNovalues(K key, ScanCursor scanCursor, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.hscanNovalues(key, scanCursor, scanArgs));
    }

    @Override
    public Mono> hscan(K key, ScanCursor scanCursor) {
        return createMono(() -> commandBuilder.hscan(key, scanCursor));
    }

    @Override
    public Mono> hscanNovalues(K key, ScanCursor scanCursor) {
        return createMono(() -> commandBuilder.hscanNovalues(key, scanCursor));
    }

    @Override
    public Mono hscan(KeyValueStreamingChannel channel, K key) {
        return createMono(() -> commandBuilder.hscanStreaming(channel, key));
    }

    @Override
    public Mono hscanNovalues(KeyStreamingChannel channel, K key) {
        return createMono(() -> commandBuilder.hscanNoValuesStreaming(channel, key));
    }

    @Override
    public Mono hscan(KeyValueStreamingChannel channel, K key, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.hscanStreaming(channel, key, scanArgs));
    }

    @Override
    public Mono hscanNovalues(KeyStreamingChannel channel, K key, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.hscanNoValuesStreaming(channel, key, scanArgs));
    }

    @Override
    public Mono hscan(KeyValueStreamingChannel channel, K key, ScanCursor scanCursor,
            ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.hscanStreaming(channel, key, scanCursor, scanArgs));
    }

    @Override
    public Mono hscanNovalues(KeyStreamingChannel channel, K key, ScanCursor scanCursor,
            ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.hscanNoValuesStreaming(channel, key, scanCursor, scanArgs));
    }

    @Override
    public Mono hscan(KeyValueStreamingChannel channel, K key, ScanCursor scanCursor) {
        return createMono(() -> commandBuilder.hscanStreaming(channel, key, scanCursor));
    }

    @Override
    public Mono hscanNovalues(KeyStreamingChannel channel, K key, ScanCursor scanCursor) {
        return createMono(() -> commandBuilder.hscanNoValuesStreaming(channel, key, scanCursor));
    }

    @Override
    public Mono hset(K key, K field, V value) {
        return createMono(() -> commandBuilder.hset(key, field, value));
    }

    @Override
    public Mono hset(K key, Map map) {
        return createMono(() -> commandBuilder.hset(key, map));
    }

    @Override
    public Mono hsetnx(K key, K field, V value) {
        return createMono(() -> commandBuilder.hsetnx(key, field, value));
    }

    @Override
    public Mono hstrlen(K key, K field) {
        return createMono(() -> commandBuilder.hstrlen(key, field));
    }

    @Override
    public Flux hvals(K key) {
        return createDissolvingFlux(() -> commandBuilder.hvals(key));
    }

    @Override
    public Mono hvals(ValueStreamingChannel channel, K key) {
        return createMono(() -> commandBuilder.hvals(channel, key));
    }

    @Override
    public Mono incr(K key) {
        return createMono(() -> commandBuilder.incr(key));
    }

    @Override
    public Mono incrby(K key, long amount) {
        return createMono(() -> commandBuilder.incrby(key, amount));
    }

    @Override
    public Mono incrbyfloat(K key, double amount) {
        return createMono(() -> commandBuilder.incrbyfloat(key, amount));
    }

    @Override
    public Mono info() {
        return createMono(commandBuilder::info);
    }

    @Override
    public Mono info(String section) {
        return createMono(() -> commandBuilder.info(section));
    }

    @Override
    public boolean isOpen() {
        return connection.isOpen();
    }

    @Override
    public Flux jsonArrappend(K key, JsonPath jsonPath, JsonValue... values) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrappend(key, jsonPath, values));
    }

    @Override
    public Flux jsonArrappend(K key, JsonValue... values) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrappend(key, JsonPath.ROOT_PATH, values));
    }

    @Override
    public Flux jsonArrindex(K key, JsonPath jsonPath, JsonValue value, JsonRangeArgs range) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrindex(key, jsonPath, value, range));
    }

    @Override
    public Flux jsonArrindex(K key, JsonPath jsonPath, JsonValue value) {
        final JsonRangeArgs args = JsonRangeArgs.Builder.defaults();
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrindex(key, jsonPath, value, args));
    }

    @Override
    public Flux jsonArrinsert(K key, JsonPath jsonPath, int index, JsonValue... values) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrinsert(key, jsonPath, index, values));
    }

    @Override
    public Flux jsonArrlen(K key, JsonPath jsonPath) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrlen(key, jsonPath));
    }

    @Override
    public Flux jsonArrlen(K key) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrlen(key, JsonPath.ROOT_PATH));
    }

    @Override
    public Flux jsonArrpop(K key, JsonPath jsonPath, int index) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrpop(key, jsonPath, index));
    }

    @Override
    public Flux jsonArrpop(K key, JsonPath jsonPath) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrpop(key, jsonPath, -1));
    }

    @Override
    public Flux jsonArrpop(K key) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrpop(key, JsonPath.ROOT_PATH, -1));
    }

    @Override
    public Flux jsonArrtrim(K key, JsonPath jsonPath, JsonRangeArgs range) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrtrim(key, jsonPath, range));
    }

    @Override
    public Mono jsonClear(K key, JsonPath jsonPath) {
        return createMono(() -> jsonCommandBuilder.jsonClear(key, jsonPath));
    }

    @Override
    public Mono jsonClear(K key) {
        return createMono(() -> jsonCommandBuilder.jsonClear(key, JsonPath.ROOT_PATH));
    }

    @Override
    public Mono jsonDel(K key, JsonPath jsonPath) {
        return createMono(() -> jsonCommandBuilder.jsonDel(key, jsonPath));
    }

    @Override
    public Mono jsonDel(K key) {
        return createMono(() -> jsonCommandBuilder.jsonDel(key, JsonPath.ROOT_PATH));
    }

    @Override
    public Flux jsonGet(K key, JsonGetArgs options, JsonPath... jsonPaths) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonGet(key, options, jsonPaths));
    }

    @Override
    public Flux jsonGet(K key, JsonPath... jsonPaths) {
        final JsonGetArgs args = JsonGetArgs.Builder.defaults();
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonGet(key, args, jsonPaths));
    }

    @Override
    public Mono jsonMerge(K key, JsonPath jsonPath, JsonValue value) {
        return createMono(() -> jsonCommandBuilder.jsonMerge(key, jsonPath, value));
    }

    @Override
    public Flux jsonMGet(JsonPath jsonPath, K... keys) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonMGet(jsonPath, keys));
    }

    @Override
    public Mono jsonMSet(List> arguments) {
        return createMono(() -> jsonCommandBuilder.jsonMSet(arguments));
    }

    @Override
    public Flux jsonNumincrby(K key, JsonPath jsonPath, Number number) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonNumincrby(key, jsonPath, number));
    }

    @Override
    public Flux jsonObjkeys(K key, JsonPath jsonPath) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonObjkeys(key, jsonPath));
    }

    @Override
    public Flux jsonObjkeys(K key) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonObjkeys(key, JsonPath.ROOT_PATH));
    }

    @Override
    public Flux jsonObjlen(K key, JsonPath jsonPath) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonObjlen(key, jsonPath));
    }

    @Override
    public Flux jsonObjlen(K key) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonObjlen(key, JsonPath.ROOT_PATH));
    }

    @Override
    public Mono jsonSet(K key, JsonPath jsonPath, JsonValue value, JsonSetArgs options) {
        return createMono(() -> jsonCommandBuilder.jsonSet(key, jsonPath, value, options));
    }

    @Override
    public Mono jsonSet(K key, JsonPath jsonPath, JsonValue value) {
        final JsonSetArgs args = JsonSetArgs.Builder.defaults();
        return createMono(() -> jsonCommandBuilder.jsonSet(key, jsonPath, value, args));
    }

    @Override
    public Flux jsonStrappend(K key, JsonPath jsonPath, JsonValue value) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonStrappend(key, jsonPath, value));
    }

    @Override
    public Flux jsonStrappend(K key, JsonValue value) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonStrappend(key, JsonPath.ROOT_PATH, value));
    }

    @Override
    public Flux jsonStrlen(K key, JsonPath jsonPath) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonStrlen(key, jsonPath));
    }

    @Override
    public Flux jsonStrlen(K key) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonStrlen(key, JsonPath.ROOT_PATH));
    }

    @Override
    public Flux jsonToggle(K key, JsonPath jsonPath) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonToggle(key, jsonPath));
    }

    @Override
    public Flux jsonType(K key, JsonPath jsonPath) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonType(key, jsonPath));
    }

    @Override
    public Flux jsonType(K key) {
        return createDissolvingFlux(() -> jsonCommandBuilder.jsonType(key, JsonPath.ROOT_PATH));
    }

    @Override
    public Flux keys(K pattern) {
        return createDissolvingFlux(() -> commandBuilder.keys(pattern));
    }

    @Override
    public Mono keys(KeyStreamingChannel channel, K pattern) {
        return createMono(() -> commandBuilder.keys(channel, pattern));
    }

    @Override
    public Mono lastsave() {
        return createMono(commandBuilder::lastsave);
    }

    @Override
    public Mono lindex(K key, long index) {
        return createMono(() -> commandBuilder.lindex(key, index));
    }

    @Override
    public Mono linsert(K key, boolean before, V pivot, V value) {
        return createMono(() -> commandBuilder.linsert(key, before, pivot, value));
    }

    @Override
    public Mono llen(K key) {
        return createMono(() -> commandBuilder.llen(key));
    }

    @Override
    public Mono lmove(K source, K destination, LMoveArgs args) {
        return createMono(() -> commandBuilder.lmove(source, destination, args));
    }

    @Override
    public Mono>> lmpop(LMPopArgs args, K... keys) {
        return createMono(() -> commandBuilder.lmpop(args, keys));
    }

    @Override
    public Mono lpop(K key) {
        return createMono(() -> commandBuilder.lpop(key));
    }

    @Override
    public Flux lpop(K key, long count) {
        return createDissolvingFlux(() -> commandBuilder.lpop(key, count));
    }

    @Override
    public Mono lpos(K key, V value) {
        return lpos(key, value, null);
    }

    @Override
    public Mono lpos(K key, V value, LPosArgs args) {
        return createMono(() -> commandBuilder.lpos(key, value, args));
    }

    @Override
    public Flux lpos(K key, V value, int count) {
        return lpos(key, value, count, null);
    }

    @Override
    public Flux lpos(K key, V value, int count, LPosArgs args) {
        return createDissolvingFlux(() -> commandBuilder.lpos(key, value, count, args));
    }

    @Override
    public Mono lpush(K key, V... values) {
        return createMono(() -> commandBuilder.lpush(key, values));
    }

    @Override
    public Mono lpushx(K key, V... values) {
        return createMono(() -> commandBuilder.lpushx(key, values));
    }

    @Override
    public Flux lrange(K key, long start, long stop) {
        return createDissolvingFlux(() -> commandBuilder.lrange(key, start, stop));
    }

    @Override
    public Mono lrange(ValueStreamingChannel channel, K key, long start, long stop) {
        return createMono(() -> commandBuilder.lrange(channel, key, start, stop));
    }

    @Override
    public Mono lrem(K key, long count, V value) {
        return createMono(() -> commandBuilder.lrem(key, count, value));
    }

    @Override
    public Mono lset(K key, long index, V value) {
        return createMono(() -> commandBuilder.lset(key, index, value));
    }

    @Override
    public Mono ltrim(K key, long start, long stop) {
        return createMono(() -> commandBuilder.ltrim(key, start, stop));
    }

    @Override
    public Mono memoryUsage(K key) {
        return createMono(() -> commandBuilder.memoryUsage(key));
    }

    @Override
    public Flux> mget(K... keys) {
        return createDissolvingFlux(() -> commandBuilder.mgetKeyValue(keys));
    }

    public Flux> mget(Iterable keys) {
        return createDissolvingFlux(() -> commandBuilder.mgetKeyValue(keys));
    }

    @Override
    public Mono mget(KeyValueStreamingChannel channel, K... keys) {
        return createMono(() -> commandBuilder.mget(channel, keys));
    }

    public Mono mget(ValueStreamingChannel channel, Iterable keys) {
        return createMono(() -> commandBuilder.mget(channel, keys));
    }

    public Mono mget(KeyValueStreamingChannel channel, Iterable keys) {
        return createMono(() -> commandBuilder.mget(channel, keys));
    }

    @Override
    public Mono migrate(String host, int port, K key, int db, long timeout) {
        return createMono(() -> commandBuilder.migrate(host, port, key, db, timeout));
    }

    @Override
    public Mono migrate(String host, int port, int db, long timeout, MigrateArgs migrateArgs) {
        return createMono(() -> commandBuilder.migrate(host, port, db, timeout, migrateArgs));
    }

    @Override
    public Mono move(K key, int db) {
        return createMono(() -> commandBuilder.move(key, db));
    }

    @Override
    public Mono mset(Map map) {
        return createMono(() -> commandBuilder.mset(map));
    }

    @Override
    public Mono msetnx(Map map) {
        return createMono(() -> commandBuilder.msetnx(map));
    }

    @Override
    public Mono multi() {
        return createMono(commandBuilder::multi);
    }

    @Override
    public Mono objectEncoding(K key) {
        return createMono(() -> commandBuilder.objectEncoding(key));
    }

    @Override
    public Mono objectFreq(K key) {
        return createMono(() -> commandBuilder.objectFreq(key));
    }

    @Override
    public Mono objectIdletime(K key) {
        return createMono(() -> commandBuilder.objectIdletime(key));
    }

    @Override
    public Mono objectRefcount(K key) {
        return createMono(() -> commandBuilder.objectRefcount(key));
    }

    @Override
    public Mono persist(K key) {
        return createMono(() -> commandBuilder.persist(key));
    }

    @Override
    public Flux hpersist(K key, K... fields) {
        return createDissolvingFlux(() -> commandBuilder.hpersist(key, fields));
    }

    @Override
    public Mono pexpire(K key, long milliseconds) {
        return pexpire(key, milliseconds, null);
    }

    @Override
    public Mono pexpire(K key, long milliseconds, ExpireArgs expireArgs) {
        return createMono(() -> commandBuilder.pexpire(key, milliseconds, expireArgs));
    }

    @Override
    public Mono pexpire(K key, Duration milliseconds) {
        return pexpire(key, milliseconds, null);
    }

    @Override
    public Mono pexpire(K key, Duration milliseconds, ExpireArgs expireArgs) {
        LettuceAssert.notNull(milliseconds, "Timeout must not be null");
        return pexpire(key, milliseconds.toMillis(), expireArgs);
    }

    @Override
    public Mono pexpireat(K key, Date timestamp) {
        return pexpireat(key, timestamp, null);
    }

    @Override
    public Mono pexpireat(K key, Date timestamp, ExpireArgs expireArgs) {
        LettuceAssert.notNull(timestamp, "Timestamp must not be null");
        return pexpireat(key, timestamp.getTime(), expireArgs);
    }

    @Override
    public Mono pexpireat(K key, Instant timestamp) {
        return pexpireat(key, timestamp, null);
    }

    @Override
    public Mono pexpireat(K key, Instant timestamp, ExpireArgs expireArgs) {
        LettuceAssert.notNull(timestamp, "Timestamp must not be null");
        return pexpireat(key, timestamp.toEpochMilli(), expireArgs);
    }

    @Override
    public Mono pexpireat(K key, long timestamp) {
        return pexpireat(key, timestamp, null);
    }

    @Override
    public Mono pexpireat(K key, long timestamp, ExpireArgs expireArgs) {
        return createMono(() -> commandBuilder.pexpireat(key, timestamp, expireArgs));
    }

    @Override
    public Mono pexpiretime(K key) {
        return createMono(() -> commandBuilder.pexpiretime(key));
    }

    @Override
    public Mono pfadd(K key, V... values) {
        return createMono(() -> commandBuilder.pfadd(key, values));
    }

    public Mono pfadd(K key, V value, V... values) {
        return createMono(() -> commandBuilder.pfadd(key, value, values));
    }

    @Override
    public Mono pfcount(K... keys) {
        return createMono(() -> commandBuilder.pfcount(keys));
    }

    public Mono pfcount(K key, K... keys) {
        return createMono(() -> commandBuilder.pfcount(key, keys));
    }

    @Override
    public Mono pfmerge(K destkey, K... sourcekeys) {
        return createMono(() -> commandBuilder.pfmerge(destkey, sourcekeys));
    }

    public Mono pfmerge(K destkey, K sourceKey, K... sourcekeys) {
        return createMono(() -> commandBuilder.pfmerge(destkey, sourceKey, sourcekeys));
    }

    @Override
    public Mono ping() {
        return createMono(commandBuilder::ping);
    }

    @Override
    public Mono psetex(K key, long milliseconds, V value) {
        return createMono(() -> commandBuilder.psetex(key, milliseconds, value));
    }

    @Override
    public Mono pttl(K key) {
        return createMono(() -> commandBuilder.pttl(key));
    }

    @Override
    public Mono publish(K channel, V message) {
        return createMono(() -> commandBuilder.publish(channel, message));
    }

    @Override
    public Flux pubsubChannels() {
        return createDissolvingFlux(commandBuilder::pubsubChannels);
    }

    @Override
    public Flux pubsubChannels(K channel) {
        return createDissolvingFlux(() -> commandBuilder.pubsubChannels(channel));
    }

    @Override
    public Mono pubsubNumpat() {
        return createMono(commandBuilder::pubsubNumpat);
    }

    @Override
    public Mono> pubsubNumsub(K... channels) {
        return createMono(() -> commandBuilder.pubsubNumsub(channels));
    }

    @Override
    public Flux pubsubShardChannels() {
        return createDissolvingFlux(commandBuilder::pubsubShardChannels);
    }

    @Override
    public Flux pubsubShardChannels(K pattern) {
        return createDissolvingFlux(() -> commandBuilder.pubsubShardChannels(pattern));
    }

    @Override
    public Mono> pubsubShardNumsub(K... shardChannels) {
        return createMono(() -> commandBuilder.pubsubShardNumsub(shardChannels));
    }

    @Override
    public Mono quit() {
        return createMono(commandBuilder::quit);
    }

    @Override
    public Mono randomkey() {
        return createMono(commandBuilder::randomkey);
    }

    @Override
    public Mono readOnly() {
        return createMono(commandBuilder::readOnly);
    }

    @Override
    public Mono readWrite() {
        return createMono(commandBuilder::readWrite);
    }

    @Override
    public Mono rename(K key, K newKey) {
        return createMono(() -> commandBuilder.rename(key, newKey));
    }

    @Override
    public Mono renamenx(K key, K newKey) {
        return createMono(() -> commandBuilder.renamenx(key, newKey));
    }

    @Override
    public Mono replicaof(String host, int port) {
        return createMono(() -> commandBuilder.replicaof(host, port));
    }

    @Override
    public Mono replicaofNoOne() {
        return createMono(() -> commandBuilder.replicaofNoOne());
    }

    @Override
    public void reset() {
        getConnection().reset();
    }

    @Override
    public Mono restore(K key, long ttl, byte[] value) {
        return createMono(() -> commandBuilder.restore(key, value, RestoreArgs.Builder.ttl(ttl)));
    }

    @Override
    public Mono restore(K key, byte[] value, RestoreArgs args) {
        return createMono(() -> commandBuilder.restore(key, value, args));
    }

    @Override
    public Flux role() {
        return createDissolvingFlux(commandBuilder::role);
    }

    @Override
    public Mono rpop(K key) {
        return createMono(() -> commandBuilder.rpop(key));
    }

    @Override
    public Flux rpop(K key, long count) {
        return createDissolvingFlux(() -> commandBuilder.rpop(key, count));
    }

    @Override
    public Mono rpoplpush(K source, K destination) {
        return createMono(() -> commandBuilder.rpoplpush(source, destination));
    }

    @Override
    public Mono rpush(K key, V... values) {
        return createMono(() -> commandBuilder.rpush(key, values));
    }

    @Override
    public Mono rpushx(K key, V... values) {
        return createMono(() -> commandBuilder.rpushx(key, values));
    }

    @Override
    public Mono sadd(K key, V... members) {
        return createMono(() -> commandBuilder.sadd(key, members));
    }

    @Override
    public Mono save() {
        return createMono(commandBuilder::save);
    }

    @Override
    public Mono> scan() {
        return createMono(commandBuilder::scan);
    }

    @Override
    public Mono> scan(ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.scan(scanArgs));
    }

    @Override
    public Mono> scan(ScanCursor scanCursor, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.scan(scanCursor, scanArgs));
    }

    @Override
    public Mono> scan(ScanCursor scanCursor) {
        return createMono(() -> commandBuilder.scan(scanCursor));
    }

    @Override
    public Mono scan(KeyStreamingChannel channel) {
        return createMono(() -> commandBuilder.scanStreaming(channel));
    }

    @Override
    public Mono scan(KeyStreamingChannel channel, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.scanStreaming(channel, scanArgs));
    }

    @Override
    public Mono scan(KeyStreamingChannel channel, ScanCursor scanCursor, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.scanStreaming(channel, scanCursor, scanArgs));
    }

    @Override
    public Mono scan(KeyStreamingChannel channel, ScanCursor scanCursor) {
        return createMono(() -> commandBuilder.scanStreaming(channel, scanCursor));
    }

    @Override
    public Mono scard(K key) {
        return createMono(() -> commandBuilder.scard(key));
    }

    @Override
    public Flux scriptExists(String... digests) {
        return createDissolvingFlux(() -> commandBuilder.scriptExists(digests));
    }

    @Override
    public Mono scriptFlush() {
        return createMono(commandBuilder::scriptFlush);
    }

    @Override
    public Mono scriptFlush(FlushMode flushMode) {
        return createMono(() -> commandBuilder.scriptFlush(flushMode));
    }

    @Override
    public Mono scriptKill() {
        return createMono(commandBuilder::scriptKill);
    }

    @Override
    public Mono scriptLoad(String script) {
        return scriptLoad(encodeScript(script));
    }

    @Override
    public Mono scriptLoad(byte[] script) {
        return createMono(() -> commandBuilder.scriptLoad(script));
    }

    @Override
    public Flux sdiff(K... keys) {
        return createDissolvingFlux(() -> commandBuilder.sdiff(keys));
    }

    @Override
    public Mono sdiff(ValueStreamingChannel channel, K... keys) {
        return createMono(() -> commandBuilder.sdiff(channel, keys));
    }

    @Override
    public Mono sdiffstore(K destination, K... keys) {
        return createMono(() -> commandBuilder.sdiffstore(destination, keys));
    }

    public Mono select(int db) {
        return createMono(() -> commandBuilder.select(db));
    }

    @Override
    public Mono set(K key, V value) {
        return createMono(() -> commandBuilder.set(key, value));
    }

    @Override
    public Mono set(K key, V value, SetArgs setArgs) {
        return createMono(() -> commandBuilder.set(key, value, setArgs));
    }

    @Override
    public Mono setGet(K key, V value) {
        return createMono(() -> commandBuilder.setGet(key, value));
    }

    @Override
    public Mono setGet(K key, V value, SetArgs setArgs) {
        return createMono(() -> commandBuilder.setGet(key, value, setArgs));
    }

    @Override
    public void setAutoFlushCommands(boolean autoFlush) {
        connection.setAutoFlushCommands(autoFlush);
    }

    @Override
    public void setTimeout(Duration timeout) {
        connection.setTimeout(timeout);
    }

    @Override
    public Mono setbit(K key, long offset, int value) {
        return createMono(() -> commandBuilder.setbit(key, offset, value));
    }

    @Override
    public Mono setex(K key, long seconds, V value) {
        return createMono(() -> commandBuilder.setex(key, seconds, value));
    }

    @Override
    public Mono setnx(K key, V value) {
        return createMono(() -> commandBuilder.setnx(key, value));
    }

    @Override
    public Mono setrange(K key, long offset, V value) {
        return createMono(() -> commandBuilder.setrange(key, offset, value));
    }

    @Override
    public Mono shutdown(boolean save) {
        return createMono(() -> commandBuilder.shutdown(save)).then();
    }

    @Override
    public Mono shutdown(ShutdownArgs args) {
        return createMono(() -> commandBuilder.shutdown(args)).then();
    }

    @Override
    public Flux sinter(K... keys) {
        return createDissolvingFlux(() -> commandBuilder.sinter(keys));
    }

    @Override
    public Mono sinter(ValueStreamingChannel channel, K... keys) {
        return createMono(() -> commandBuilder.sinter(channel, keys));
    }

    @Override
    public Mono sintercard(K... keys) {
        return createMono(() -> commandBuilder.sintercard(keys));
    }

    @Override
    public Mono sintercard(long limit, K... keys) {
        return createMono(() -> commandBuilder.sintercard(limit, keys));
    }

    @Override
    public Mono sinterstore(K destination, K... keys) {
        return createMono(() -> commandBuilder.sinterstore(destination, keys));
    }

    @Override
    public Mono sismember(K key, V member) {
        return createMono(() -> commandBuilder.sismember(key, member));
    }

    @Override
    public Mono slaveof(String host, int port) {
        return createMono(() -> commandBuilder.slaveof(host, port));
    }

    @Override
    public Mono slaveofNoOne() {
        return createMono(() -> commandBuilder.slaveofNoOne());
    }

    @Override
    public Flux slowlogGet() {
        return createDissolvingFlux(() -> commandBuilder.slowlogGet());
    }

    @Override
    public Flux slowlogGet(int count) {
        return createDissolvingFlux(() -> commandBuilder.slowlogGet(count));
    }

    @Override
    public Mono slowlogLen() {
        return createMono(() -> commandBuilder.slowlogLen());
    }

    @Override
    public Mono slowlogReset() {
        return createMono(() -> commandBuilder.slowlogReset());
    }

    @Override
    public Flux smembers(K key) {
        return createDissolvingFlux(() -> commandBuilder.smembers(key));
    }

    @Override
    public Mono smembers(ValueStreamingChannel channel, K key) {
        return createMono(() -> commandBuilder.smembers(channel, key));
    }

    @Override
    public Flux smismember(K key, V... members) {
        return createDissolvingFlux(() -> commandBuilder.smismember(key, members));
    }

    @Override
    public Mono smove(K source, K destination, V member) {
        return createMono(() -> commandBuilder.smove(source, destination, member));
    }

    @Override
    public Flux sort(K key) {
        return createDissolvingFlux(() -> commandBuilder.sort(key));
    }

    @Override
    public Mono sort(ValueStreamingChannel channel, K key) {
        return createMono(() -> commandBuilder.sort(channel, key));
    }

    @Override
    public Flux sort(K key, SortArgs sortArgs) {
        return createDissolvingFlux(() -> commandBuilder.sort(key, sortArgs));
    }

    @Override
    public Mono sort(ValueStreamingChannel channel, K key, SortArgs sortArgs) {
        return createMono(() -> commandBuilder.sort(channel, key, sortArgs));
    }

    @Override
    public Flux sortReadOnly(K key) {
        return createDissolvingFlux(() -> commandBuilder.sortReadOnly(key));
    }

    @Override
    public Mono sortReadOnly(ValueStreamingChannel channel, K key) {
        return createMono(() -> commandBuilder.sortReadOnly(channel, key));
    }

    @Override
    public Flux sortReadOnly(K key, SortArgs sortArgs) {
        return createDissolvingFlux(() -> commandBuilder.sortReadOnly(key, sortArgs));
    }

    @Override
    public Mono sortReadOnly(ValueStreamingChannel channel, K key, SortArgs sortArgs) {
        return createMono(() -> commandBuilder.sortReadOnly(channel, key, sortArgs));
    }

    @Override
    public Mono sortStore(K key, SortArgs sortArgs, K destination) {
        return createMono(() -> commandBuilder.sortStore(key, sortArgs, destination));
    }

    @Override
    public Mono spop(K key) {
        return createMono(() -> commandBuilder.spop(key));
    }

    @Override
    public Flux spop(K key, long count) {
        return createDissolvingFlux(() -> commandBuilder.spop(key, count));
    }

    @Override
    public Mono spublish(K shardChannel, V message) {
        return createMono(() -> commandBuilder.spublish(shardChannel, message));
    }

    @Override
    public Mono srandmember(K key) {
        return createMono(() -> commandBuilder.srandmember(key));
    }

    @Override
    public Flux srandmember(K key, long count) {
        return createDissolvingFlux(() -> commandBuilder.srandmember(key, count));
    }

    @Override
    public Mono srandmember(ValueStreamingChannel channel, K key, long count) {
        return createMono(() -> commandBuilder.srandmember(channel, key, count));
    }

    @Override
    public Mono srem(K key, V... members) {
        return createMono(() -> commandBuilder.srem(key, members));
    }

    @Override
    public Mono> sscan(K key) {
        return createMono(() -> commandBuilder.sscan(key));
    }

    @Override
    public Mono> sscan(K key, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.sscan(key, scanArgs));
    }

    @Override
    public Mono> sscan(K key, ScanCursor scanCursor, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.sscan(key, scanCursor, scanArgs));
    }

    @Override
    public Mono> sscan(K key, ScanCursor scanCursor) {
        return createMono(() -> commandBuilder.sscan(key, scanCursor));
    }

    @Override
    public Mono sscan(ValueStreamingChannel channel, K key) {
        return createMono(() -> commandBuilder.sscanStreaming(channel, key));
    }

    @Override
    public Mono sscan(ValueStreamingChannel channel, K key, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.sscanStreaming(channel, key, scanArgs));
    }

    @Override
    public Mono sscan(ValueStreamingChannel channel, K key, ScanCursor scanCursor, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.sscanStreaming(channel, key, scanCursor, scanArgs));
    }

    @Override
    public Mono sscan(ValueStreamingChannel channel, K key, ScanCursor scanCursor) {
        return createMono(() -> commandBuilder.sscanStreaming(channel, key, scanCursor));
    }

    @Override
    public Mono strlen(K key) {
        return createMono(() -> commandBuilder.strlen(key));
    }

    @Override
    public Mono stralgoLcs(StrAlgoArgs strAlgoArgs) {
        return createMono(() -> commandBuilder.stralgoLcs(strAlgoArgs));
    }

    @Override
    public Mono lcs(LcsArgs lcsArgs) {
        return createMono(() -> commandBuilder.lcs(lcsArgs));
    }

    @Override
    public Flux sunion(K... keys) {
        return createDissolvingFlux(() -> commandBuilder.sunion(keys));
    }

    @Override
    public Mono sunion(ValueStreamingChannel channel, K... keys) {
        return createMono(() -> commandBuilder.sunion(channel, keys));
    }

    @Override
    public Mono sunionstore(K destination, K... keys) {
        return createMono(() -> commandBuilder.sunionstore(destination, keys));
    }

    public Mono swapdb(int db1, int db2) {
        return createMono(() -> commandBuilder.swapdb(db1, db2));
    }

    @Override
    public Flux time() {
        return createDissolvingFlux(commandBuilder::time);
    }

    @Override
    public Mono touch(K... keys) {
        return createMono(() -> commandBuilder.touch(keys));
    }

    public Mono touch(Iterable keys) {
        return createMono(() -> commandBuilder.touch(keys));
    }

    @Override
    public Mono ttl(K key) {
        return createMono(() -> commandBuilder.ttl(key));
    }

    @Override
    public Mono type(K key) {
        return createMono(() -> commandBuilder.type(key));
    }

    @Override
    public Mono unlink(K... keys) {
        return createMono(() -> commandBuilder.unlink(keys));
    }

    public Mono unlink(Iterable keys) {
        return createMono(() -> commandBuilder.unlink(keys));
    }

    @Override
    public Mono copy(K source, K destination) {
        return createMono(() -> commandBuilder.copy(source, destination));
    }

    @Override
    public Mono copy(K source, K destination, CopyArgs copyArgs) {
        return createMono(() -> commandBuilder.copy(source, destination, copyArgs));
    }

    @Override
    public Mono unwatch() {
        return createMono(commandBuilder::unwatch);
    }

    @Override
    public Mono waitForReplication(int replicas, long timeout) {
        return createMono(() -> commandBuilder.wait(replicas, timeout));
    }

    @Override
    public Mono watch(K... keys) {
        return createMono(() -> commandBuilder.watch(keys));
    }

    @Override
    public Mono xack(K key, K group, String... messageIds) {
        return createMono(() -> commandBuilder.xack(key, group, messageIds));
    }

    @Override
    public Mono xadd(K key, Map body) {
        return createMono(() -> commandBuilder.xadd(key, null, body));
    }

    @Override
    public Mono xadd(K key, XAddArgs args, Map body) {
        return createMono(() -> commandBuilder.xadd(key, args, body));
    }

    @Override
    public Mono xadd(K key, Object... keysAndValues) {
        return createMono(() -> commandBuilder.xadd(key, null, keysAndValues));
    }

    @Override
    public Mono xadd(K key, XAddArgs args, Object... keysAndValues) {
        return createMono(() -> commandBuilder.xadd(key, args, keysAndValues));
    }

    @Override
    public Mono> xautoclaim(K key, XAutoClaimArgs args) {
        return createMono(() -> commandBuilder.xautoclaim(key, args));
    }

    @Override
    public Flux> xclaim(K key, Consumer consumer, long minIdleTime, String... messageIds) {
        return createDissolvingFlux(
                () -> commandBuilder.xclaim(key, consumer, XClaimArgs.Builder.minIdleTime(minIdleTime), messageIds));
    }

    @Override
    public Flux> xclaim(K key, Consumer consumer, XClaimArgs args, String... messageIds) {
        return createDissolvingFlux(() -> commandBuilder.xclaim(key, consumer, args, messageIds));
    }

    @Override
    public Mono xdel(K key, String... messageIds) {
        return createMono(() -> commandBuilder.xdel(key, messageIds));
    }

    @Override
    public Mono xgroupCreate(XReadArgs.StreamOffset streamOffset, K group) {
        return createMono(() -> commandBuilder.xgroupCreate(streamOffset, group, null));
    }

    @Override
    public Mono xgroupCreate(XReadArgs.StreamOffset streamOffset, K group, XGroupCreateArgs args) {
        return createMono(() -> commandBuilder.xgroupCreate(streamOffset, group, args));
    }

    @Override
    public Mono xgroupCreateconsumer(K key, Consumer consumer) {
        return createMono(() -> commandBuilder.xgroupCreateconsumer(key, consumer));
    }

    @Override
    public Mono xgroupDelconsumer(K key, Consumer consumer) {
        return createMono(() -> commandBuilder.xgroupDelconsumer(key, consumer));
    }

    @Override
    public Mono xgroupDestroy(K key, K group) {
        return createMono(() -> commandBuilder.xgroupDestroy(key, group));
    }

    @Override
    public Mono xgroupSetid(XReadArgs.StreamOffset streamOffset, K group) {
        return createMono(() -> commandBuilder.xgroupSetid(streamOffset, group));
    }

    @Override
    public Flux xinfoStream(K key) {
        return createDissolvingFlux(() -> commandBuilder.xinfoStream(key));
    }

    @Override
    public Flux xinfoGroups(K key) {
        return createDissolvingFlux(() -> commandBuilder.xinfoGroups(key));
    }

    @Override
    public Flux xinfoConsumers(K key, K group) {
        return createDissolvingFlux(() -> commandBuilder.xinfoConsumers(key, group));
    }

    @Override
    public Mono xlen(K key) {
        return createMono(() -> commandBuilder.xlen(key));
    }

    @Override
    public Mono xpending(K key, K group) {
        return createMono(() -> commandBuilder.xpending(key, group));
    }

    @Override
    public Flux xpending(K key, K group, Range range, Limit limit) {
        return createDissolvingFlux(() -> commandBuilder.xpending(key, group, range, limit));
    }

    @Override
    public Flux xpending(K key, Consumer consumer, Range range, Limit limit) {
        return createDissolvingFlux(() -> commandBuilder.xpending(key, consumer, range, limit));
    }

    @Override
    public Flux xpending(K key, XPendingArgs args) {
        return createDissolvingFlux(() -> commandBuilder.xpending(key, args));
    }

    @Override
    public Flux> xrange(K key, Range range) {
        return createDissolvingFlux(() -> commandBuilder.xrange(key, range, Limit.unlimited()));
    }

    @Override
    public Flux> xrange(K key, Range range, Limit limit) {
        return createDissolvingFlux(() -> commandBuilder.xrange(key, range, limit));
    }

    @Override
    public Flux> xread(XReadArgs.StreamOffset... streams) {
        return createDissolvingFlux(() -> commandBuilder.xread(null, streams));
    }

    @Override
    public Flux> xread(XReadArgs args, XReadArgs.StreamOffset... streams) {
        return createDissolvingFlux(() -> commandBuilder.xread(args, streams));
    }

    @Override
    public Flux> xreadgroup(Consumer consumer, XReadArgs.StreamOffset... streams) {
        return createDissolvingFlux(() -> commandBuilder.xreadgroup(consumer, null, streams));
    }

    @Override
    public Flux> xreadgroup(Consumer consumer, XReadArgs args, XReadArgs.StreamOffset... streams) {
        return createDissolvingFlux(() -> commandBuilder.xreadgroup(consumer, args, streams));
    }

    @Override
    public Flux> xrevrange(K key, Range range) {
        return xrevrange(key, range, Limit.unlimited());
    }

    @Override
    public Flux> xrevrange(K key, Range range, Limit limit) {
        return createDissolvingFlux(() -> commandBuilder.xrevrange(key, range, limit));
    }

    @Override
    public Mono xtrim(K key, long count) {
        return xtrim(key, false, count);
    }

    @Override
    public Mono xtrim(K key, boolean approximateTrimming, long count) {
        return createMono(() -> commandBuilder.xtrim(key, approximateTrimming, count));
    }

    @Override
    public Mono xtrim(K key, XTrimArgs args) {
        return createMono(() -> commandBuilder.xtrim(key, args));
    }

    @Override
    public Mono>> bzmpop(long timeout, ZPopArgs args, K... keys) {
        return createMono(() -> commandBuilder.bzmpop(timeout, args, keys));
    }

    @Override
    public Mono>>> bzmpop(long timeout, long count, ZPopArgs args, K... keys) {
        return createMono(() -> commandBuilder.bzmpop(timeout, count, args, keys));
    }

    @Override
    public Mono>> bzmpop(double timeout, ZPopArgs args, K... keys) {
        return createMono(() -> commandBuilder.bzmpop(timeout, args, keys));
    }

    @Override
    public Mono>>> bzmpop(double timeout, int count, ZPopArgs args, K... keys) {
        return createMono(() -> commandBuilder.bzmpop(timeout, count, args, keys));
    }

    @Override
    public Mono>> bzpopmin(long timeout, K... keys) {
        return createMono(() -> commandBuilder.bzpopmin(timeout, keys));
    }

    @Override
    public Mono>> bzpopmin(double timeout, K... keys) {
        return createMono(() -> commandBuilder.bzpopmin(timeout, keys));
    }

    @Override
    public Mono>> bzpopmax(long timeout, K... keys) {
        return createMono(() -> commandBuilder.bzpopmax(timeout, keys));
    }

    @Override
    public Mono>> bzpopmax(double timeout, K... keys) {
        return createMono(() -> commandBuilder.bzpopmax(timeout, keys));
    }

    @Override
    public Mono zadd(K key, double score, V member) {
        return createMono(() -> commandBuilder.zadd(key, null, score, member));
    }

    @Override
    public Mono zadd(K key, Object... scoresAndValues) {
        return createMono(() -> commandBuilder.zadd(key, null, scoresAndValues));
    }

    @Override
    public Mono zadd(K key, ScoredValue... scoredValues) {
        return createMono(() -> commandBuilder.zadd(key, null, (Object[]) scoredValues));
    }

    @Override
    public Mono zadd(K key, ZAddArgs zAddArgs, double score, V member) {
        return createMono(() -> commandBuilder.zadd(key, zAddArgs, score, member));
    }

    @Override
    public Mono zadd(K key, ZAddArgs zAddArgs, Object... scoresAndValues) {
        return createMono(() -> commandBuilder.zadd(key, zAddArgs, scoresAndValues));
    }

    @Override
    public Mono zadd(K key, ZAddArgs zAddArgs, ScoredValue... scoredValues) {
        return createMono(() -> commandBuilder.zadd(key, zAddArgs, (Object[]) scoredValues));
    }

    @Override
    public Mono zaddincr(K key, double score, V member) {
        return createMono(() -> commandBuilder.zaddincr(key, null, score, member));
    }

    @Override
    public Mono zaddincr(K key, ZAddArgs zAddArgs, double score, V member) {
        return createMono(() -> commandBuilder.zaddincr(key, zAddArgs, score, member));
    }

    @Override
    public Mono zcard(K key) {
        return createMono(() -> commandBuilder.zcard(key));
    }

    public Mono zcount(K key, double min, double max) {
        return createMono(() -> commandBuilder.zcount(key, min, max));
    }

    @Override
    public Mono zcount(K key, String min, String max) {
        return createMono(() -> commandBuilder.zcount(key, min, max));
    }

    @Override
    public Mono zcount(K key, Range range) {
        return createMono(() -> commandBuilder.zcount(key, range));
    }

    @Override
    public Flux zdiff(K... keys) {
        return createDissolvingFlux(() -> commandBuilder.zdiff(keys));
    }

    @Override
    public Mono zdiffstore(K destKey, K... srcKeys) {
        return createMono(() -> commandBuilder.zdiffstore(destKey, srcKeys));
    }

    @Override
    public Flux> zdiffWithScores(K... keys) {
        return createDissolvingFlux(() -> commandBuilder.zdiffWithScores(keys));
    }

    @Override
    public Mono zincrby(K key, double amount, V member) {
        return createMono(() -> commandBuilder.zincrby(key, amount, member));
    }

    @Override
    public Flux zinter(K... keys) {
        return createDissolvingFlux(() -> commandBuilder.zinter(keys));
    }

    @Override
    public Flux zinter(ZAggregateArgs aggregateArgs, K... keys) {
        return createDissolvingFlux(() -> commandBuilder.zinter(aggregateArgs, keys));
    }

    @Override
    public Mono zintercard(K... keys) {
        return createMono(() -> commandBuilder.zintercard(keys));
    }

    @Override
    public Mono zintercard(long limit, K... keys) {
        return createMono(() -> commandBuilder.zintercard(limit, keys));
    }

    @Override
    public Flux> zinterWithScores(K... keys) {
        return createDissolvingFlux(() -> commandBuilder.zinterWithScores(keys));
    }

    @Override
    public Flux> zinterWithScores(ZAggregateArgs aggregateArgs, K... keys) {
        return createDissolvingFlux(() -> commandBuilder.zinterWithScores(aggregateArgs, keys));
    }

    @Override
    public Mono zinterstore(K destination, K... keys) {
        return createMono(() -> commandBuilder.zinterstore(destination, keys));
    }

    @Override
    public Mono zinterstore(K destination, ZStoreArgs zStoreArgs, K... keys) {
        return createMono(() -> commandBuilder.zinterstore(destination, zStoreArgs, keys));
    }

    @Override
    public Mono zlexcount(K key, String min, String max) {
        return createMono(() -> commandBuilder.zlexcount(key, min, max));
    }

    @Override
    public Mono zlexcount(K key, Range range) {
        return createMono(() -> commandBuilder.zlexcount(key, range));
    }

    @Override
    public Mono> zmscore(K key, V... members) {
        return createMono(() -> commandBuilder.zmscore(key, members));
    }

    @Override
    public Mono>> zmpop(ZPopArgs args, K... keys) {
        return createMono(() -> commandBuilder.zmpop(args, keys));
    }

    @Override
    public Mono>>> zmpop(int count, ZPopArgs args, K... keys) {
        return createMono(() -> commandBuilder.zmpop(count, args, keys));
    }

    @Override
    public Mono> zpopmin(K key) {
        return createMono(() -> commandBuilder.zpopmin(key));
    }

    @Override
    public Flux> zpopmin(K key, long count) {
        return createDissolvingFlux(() -> commandBuilder.zpopmin(key, count));
    }

    @Override
    public Mono> zpopmax(K key) {
        return createMono(() -> commandBuilder.zpopmax(key));
    }

    @Override
    public Flux> zpopmax(K key, long count) {
        return createDissolvingFlux(() -> commandBuilder.zpopmax(key, count));
    }

    @Override
    public Mono zrandmember(K key) {
        return createMono(() -> commandBuilder.zrandmember(key));
    }

    @Override
    public Flux zrandmember(K key, long count) {
        return createDissolvingFlux(() -> commandBuilder.zrandmember(key, count));
    }

    @Override
    public Mono> zrandmemberWithScores(K key) {
        return createMono(() -> commandBuilder.zrandmemberWithScores(key));
    }

    @Override
    public Flux> zrandmemberWithScores(K key, long count) {
        return createDissolvingFlux(() -> commandBuilder.zrandmemberWithScores(key, count));
    }

    @Override
    public Flux zrange(K key, long start, long stop) {
        return createDissolvingFlux(() -> commandBuilder.zrange(key, start, stop));
    }

    @Override
    public Mono zrange(ValueStreamingChannel channel, K key, long start, long stop) {
        return createMono(() -> commandBuilder.zrange(channel, key, start, stop));
    }

    @Override
    public Flux> zrangeWithScores(K key, long start, long stop) {
        return createDissolvingFlux(() -> commandBuilder.zrangeWithScores(key, start, stop));
    }

    @Override
    public Mono zrangeWithScores(ScoredValueStreamingChannel channel, K key, long start, long stop) {
        return createMono(() -> commandBuilder.zrangeWithScores(channel, key, start, stop));
    }

    @Override
    public Flux zrangebylex(K key, String min, String max) {
        return createDissolvingFlux(() -> commandBuilder.zrangebylex(key, min, max));
    }

    @Override
    public Flux zrangebylex(K key, Range range) {
        return createDissolvingFlux(() -> commandBuilder.zrangebylex(key, range, Limit.unlimited()));
    }

    @Override
    public Flux zrangebylex(K key, String min, String max, long offset, long count) {
        return createDissolvingFlux(() -> commandBuilder.zrangebylex(key, min, max, offset, count));
    }

    @Override
    public Flux zrangebylex(K key, Range range, Limit limit) {
        return createDissolvingFlux(() -> commandBuilder.zrangebylex(key, range, limit));
    }

    @Override
    public Flux zrangebyscore(K key, double min, double max) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscore(key, min, max));
    }

    @Override
    public Flux zrangebyscore(K key, String min, String max) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscore(key, min, max));
    }

    @Override
    public Flux zrangebyscore(K key, double min, double max, long offset, long count) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscore(key, min, max, offset, count));
    }

    @Override
    public Flux zrangebyscore(K key, String min, String max, long offset, long count) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscore(key, min, max, offset, count));
    }

    @Override
    public Flux zrangebyscore(K key, Range range) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscore(key, range, Limit.unlimited()));
    }

    @Override
    public Flux zrangebyscore(K key, Range range, Limit limit) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscore(key, range, limit));
    }

    @Override
    public Mono zrangebyscore(ValueStreamingChannel channel, K key, double min, double max) {
        return createMono(() -> commandBuilder.zrangebyscore(channel, key, min, max));
    }

    @Override
    public Mono zrangebyscore(ValueStreamingChannel channel, K key, String min, String max) {
        return createMono(() -> commandBuilder.zrangebyscore(channel, key, min, max));
    }

    @Override
    public Mono zrangebyscore(ValueStreamingChannel channel, K key, double min, double max, long offset, long count) {
        return createMono(() -> commandBuilder.zrangebyscore(channel, key, min, max, offset, count));
    }

    @Override
    public Mono zrangebyscore(ValueStreamingChannel channel, K key, Range range) {
        return createMono(() -> commandBuilder.zrangebyscore(channel, key, range, Limit.unlimited()));
    }

    @Override
    public Mono zrangebyscore(ValueStreamingChannel channel, K key, String min, String max, long offset, long count) {
        return createMono(() -> commandBuilder.zrangebyscore(channel, key, min, max, offset, count));
    }

    @Override
    public Mono zrangebyscore(ValueStreamingChannel channel, K key, Range range, Limit limit) {
        return createMono(() -> commandBuilder.zrangebyscore(channel, key, range, limit));
    }

    @Override
    public Flux> zrangebyscoreWithScores(K key, double min, double max) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscoreWithScores(key, min, max));
    }

    @Override
    public Flux> zrangebyscoreWithScores(K key, String min, String max) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscoreWithScores(key, min, max));
    }

    @Override
    public Flux> zrangebyscoreWithScores(K key, double min, double max, long offset, long count) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscoreWithScores(key, min, max, offset, count));
    }

    @Override
    public Flux> zrangebyscoreWithScores(K key, String min, String max, long offset, long count) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscoreWithScores(key, min, max, offset, count));
    }

    @Override
    public Flux> zrangebyscoreWithScores(K key, Range range) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscoreWithScores(key, range, Limit.unlimited()));
    }

    @Override
    public Flux> zrangebyscoreWithScores(K key, Range range, Limit limit) {
        return createDissolvingFlux(() -> commandBuilder.zrangebyscoreWithScores(key, range, limit));
    }

    @Override
    public Mono zrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, double min, double max) {
        return createMono(() -> commandBuilder.zrangebyscoreWithScores(channel, key, min, max));
    }

    @Override
    public Mono zrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, String min, String max) {
        return createMono(() -> commandBuilder.zrangebyscoreWithScores(channel, key, min, max));
    }

    @Override
    public Mono zrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, Range range) {
        return createMono(() -> commandBuilder.zrangebyscoreWithScores(channel, key, range, Limit.unlimited()));
    }

    @Override
    public Mono zrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, double min, double max,
            long offset, long count) {
        return createMono(() -> commandBuilder.zrangebyscoreWithScores(channel, key, min, max, offset, count));
    }

    @Override
    public Mono zrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, String min, String max,
            long offset, long count) {
        return createMono(() -> commandBuilder.zrangebyscoreWithScores(channel, key, min, max, offset, count));
    }

    @Override
    public Mono zrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, Range range,
            Limit limit) {
        return createMono(() -> commandBuilder.zrangebyscoreWithScores(channel, key, range, limit));
    }

    @Override
    public Mono zrangestore(K dstKey, K srcKey, Range range) {
        return createMono(() -> commandBuilder.zrangestore(dstKey, srcKey, range, false));
    }

    @Override
    public Mono zrangestorebylex(K dstKey, K srcKey, Range range, Limit limit) {
        return createMono(() -> commandBuilder.zrangestorebylex(dstKey, srcKey, range, limit, false));
    }

    @Override
    public Mono zrangestorebyscore(K dstKey, K srcKey, Range range, Limit limit) {
        return createMono(() -> commandBuilder.zrangestorebyscore(dstKey, srcKey, range, limit, false));
    }

    @Override
    public Mono zrank(K key, V member) {
        return createMono(() -> commandBuilder.zrank(key, member));
    }

    @Override
    public Mono> zrankWithScore(K key, V member) {
        return createMono(() -> commandBuilder.zrankWithScore(key, member));
    }

    @Override
    public Mono zrem(K key, V... members) {
        return createMono(() -> commandBuilder.zrem(key, members));
    }

    @Override
    public Mono zremrangebylex(K key, String min, String max) {
        return createMono(() -> commandBuilder.zremrangebylex(key, min, max));
    }

    @Override
    public Mono zremrangebylex(K key, Range range) {
        return createMono(() -> commandBuilder.zremrangebylex(key, range));
    }

    @Override
    public Mono zremrangebyrank(K key, long start, long stop) {
        return createMono(() -> commandBuilder.zremrangebyrank(key, start, stop));
    }

    @Override
    public Mono zremrangebyscore(K key, double min, double max) {
        return createMono(() -> commandBuilder.zremrangebyscore(key, min, max));
    }

    @Override
    public Mono zremrangebyscore(K key, String min, String max) {
        return createMono(() -> commandBuilder.zremrangebyscore(key, min, max));
    }

    @Override
    public Mono zremrangebyscore(K key, Range range) {
        return createMono(() -> commandBuilder.zremrangebyscore(key, range));
    }

    @Override
    public Flux zrevrange(K key, long start, long stop) {
        return createDissolvingFlux(() -> commandBuilder.zrevrange(key, start, stop));
    }

    @Override
    public Mono zrevrange(ValueStreamingChannel channel, K key, long start, long stop) {
        return createMono(() -> commandBuilder.zrevrange(channel, key, start, stop));
    }

    @Override
    public Flux> zrevrangeWithScores(K key, long start, long stop) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangeWithScores(key, start, stop));
    }

    @Override
    public Mono zrevrangeWithScores(ScoredValueStreamingChannel channel, K key, long start, long stop) {
        return createMono(() -> commandBuilder.zrevrangeWithScores(channel, key, start, stop));
    }

    @Override
    public Flux zrevrangebylex(K key, Range range) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebylex(key, range, Limit.unlimited()));
    }

    @Override
    public Flux zrevrangebylex(K key, Range range, Limit limit) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebylex(key, range, limit));
    }

    @Override
    public Flux zrevrangebyscore(K key, double max, double min) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscore(key, max, min));
    }

    @Override
    public Flux zrevrangebyscore(K key, String max, String min) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscore(key, max, min));
    }

    @Override
    public Flux zrevrangebyscore(K key, Range range) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscore(key, range, Limit.unlimited()));
    }

    @Override
    public Flux zrevrangebyscore(K key, double max, double min, long offset, long count) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscore(key, max, min, offset, count));
    }

    @Override
    public Flux zrevrangebyscore(K key, String max, String min, long offset, long count) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscore(key, max, min, offset, count));
    }

    @Override
    public Flux zrevrangebyscore(K key, Range range, Limit limit) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscore(key, range, limit));
    }

    @Override
    public Mono zrevrangebyscore(ValueStreamingChannel channel, K key, double max, double min) {
        return createMono(() -> commandBuilder.zrevrangebyscore(channel, key, max, min));
    }

    @Override
    public Mono zrevrangebyscore(ValueStreamingChannel channel, K key, String max, String min) {
        return createMono(() -> commandBuilder.zrevrangebyscore(channel, key, max, min));
    }

    @Override
    public Mono zrevrangebyscore(ValueStreamingChannel channel, K key, Range range) {
        return createMono(() -> commandBuilder.zrevrangebyscore(channel, key, range, Limit.unlimited()));
    }

    @Override
    public Mono zrevrangebyscore(ValueStreamingChannel channel, K key, double max, double min, long offset,
            long count) {
        return createMono(() -> commandBuilder.zrevrangebyscore(channel, key, max, min, offset, count));
    }

    @Override
    public Mono zrevrangebyscore(ValueStreamingChannel channel, K key, String max, String min, long offset,
            long count) {
        return createMono(() -> commandBuilder.zrevrangebyscore(channel, key, max, min, offset, count));
    }

    @Override
    public Mono zrevrangebyscore(ValueStreamingChannel channel, K key, Range range, Limit limit) {
        return createMono(() -> commandBuilder.zrevrangebyscore(channel, key, range, limit));
    }

    @Override
    public Flux> zrevrangebyscoreWithScores(K key, double max, double min) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscoreWithScores(key, max, min));
    }

    @Override
    public Flux> zrevrangebyscoreWithScores(K key, String max, String min) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscoreWithScores(key, max, min));
    }

    @Override
    public Flux> zrevrangebyscoreWithScores(K key, Range range) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscoreWithScores(key, range, Limit.unlimited()));
    }

    @Override
    public Flux> zrevrangebyscoreWithScores(K key, double max, double min, long offset, long count) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscoreWithScores(key, max, min, offset, count));
    }

    @Override
    public Flux> zrevrangebyscoreWithScores(K key, String max, String min, long offset, long count) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscoreWithScores(key, max, min, offset, count));
    }

    @Override
    public Flux> zrevrangebyscoreWithScores(K key, Range range, Limit limit) {
        return createDissolvingFlux(() -> commandBuilder.zrevrangebyscoreWithScores(key, range, limit));
    }

    @Override
    public Mono zrevrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, double max, double min) {
        return createMono(() -> commandBuilder.zrevrangebyscoreWithScores(channel, key, max, min));
    }

    @Override
    public Mono zrevrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, String max, String min) {
        return createMono(() -> commandBuilder.zrevrangebyscoreWithScores(channel, key, max, min));
    }

    @Override
    public Mono zrevrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, Range range) {
        return createMono(() -> commandBuilder.zrevrangebyscoreWithScores(channel, key, range, Limit.unlimited()));
    }

    @Override
    public Mono zrevrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, double max, double min,
            long offset, long count) {
        return createMono(() -> commandBuilder.zrevrangebyscoreWithScores(channel, key, max, min, offset, count));
    }

    @Override
    public Mono zrevrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, String max, String min,
            long offset, long count) {
        return createMono(() -> commandBuilder.zrevrangebyscoreWithScores(channel, key, max, min, offset, count));
    }

    @Override
    public Mono zrevrangebyscoreWithScores(ScoredValueStreamingChannel channel, K key, Range range,
            Limit limit) {
        return createMono(() -> commandBuilder.zrevrangebyscoreWithScores(channel, key, range, limit));
    }

    @Override
    public Mono zrevrangestore(K dstKey, K srcKey, Range range) {
        return createMono(() -> commandBuilder.zrangestore(dstKey, srcKey, range, true));
    }

    @Override
    public Mono zrevrangestorebylex(K dstKey, K srcKey, Range range, Limit limit) {
        return createMono(() -> commandBuilder.zrangestorebylex(dstKey, srcKey, range, limit, true));
    }

    @Override
    public Mono zrevrangestorebyscore(K dstKey, K srcKey, Range range, Limit limit) {
        return createMono(() -> commandBuilder.zrangestorebyscore(dstKey, srcKey, range, limit, true));
    }

    @Override
    public Mono zrevrank(K key, V member) {
        return createMono(() -> commandBuilder.zrevrank(key, member));
    }

    @Override
    public Mono> zrevrankWithScore(K key, V member) {
        return createMono(() -> commandBuilder.zrevrankWithScore(key, member));
    }

    @Override
    public Mono> zscan(K key) {
        return createMono(() -> commandBuilder.zscan(key));
    }

    @Override
    public Mono> zscan(K key, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.zscan(key, scanArgs));
    }

    @Override
    public Mono> zscan(K key, ScanCursor scanCursor, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.zscan(key, scanCursor, scanArgs));
    }

    @Override
    public Mono> zscan(K key, ScanCursor scanCursor) {
        return createMono(() -> commandBuilder.zscan(key, scanCursor));
    }

    @Override
    public Mono zscan(ScoredValueStreamingChannel channel, K key) {
        return createMono(() -> commandBuilder.zscanStreaming(channel, key));
    }

    @Override
    public Mono zscan(ScoredValueStreamingChannel channel, K key, ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.zscanStreaming(channel, key, scanArgs));
    }

    @Override
    public Mono zscan(ScoredValueStreamingChannel channel, K key, ScanCursor scanCursor,
            ScanArgs scanArgs) {
        return createMono(() -> commandBuilder.zscanStreaming(channel, key, scanCursor, scanArgs));
    }

    @Override
    public Mono zscan(ScoredValueStreamingChannel channel, K key, ScanCursor scanCursor) {
        return createMono(() -> commandBuilder.zscanStreaming(channel, key, scanCursor));
    }

    @Override
    public Mono zscore(K key, V member) {
        return createMono(() -> commandBuilder.zscore(key, member));
    }

    @Override
    public Flux zunion(K... keys) {
        return createDissolvingFlux(() -> commandBuilder.zunion(keys));
    }

    @Override
    public Flux zunion(ZAggregateArgs aggregateArgs, K... keys) {
        return createDissolvingFlux(() -> commandBuilder.zunion(aggregateArgs, keys));
    }

    @Override
    public Flux> zunionWithScores(K... keys) {
        return createDissolvingFlux(() -> commandBuilder.zunionWithScores(keys));
    }

    @Override
    public Flux> zunionWithScores(ZAggregateArgs aggregateArgs, K... keys) {
        return createDissolvingFlux(() -> commandBuilder.zunionWithScores(aggregateArgs, keys));
    }

    @Override
    public Mono zunionstore(K destination, K... keys) {
        return createMono(() -> commandBuilder.zunionstore(destination, keys));
    }

    @Override
    public Mono zunionstore(K destination, ZStoreArgs zStoreArgs, K... keys) {
        return createMono(() -> commandBuilder.zunionstore(destination, zStoreArgs, keys));
    }

    @Override
    public Mono>> clusterLinks() {
        return createMono(commandBuilder::clusterLinks);
    }

    private byte[] encodeFunction(String functionCode) {
        LettuceAssert.notNull(functionCode, "Function code must not be null");
        LettuceAssert.notEmpty(functionCode, "Function code script must not be empty");
        return functionCode.getBytes(getConnection().getOptions().getScriptCharset());
    }

    private byte[] encodeScript(String script) {
        LettuceAssert.notNull(script, "Lua script must not be null");
        LettuceAssert.notEmpty(script, "Lua script must not be empty");
        return script.getBytes(getConnection().getOptions().getScriptCharset());
    }

}