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

org.springframework.data.redis.connection.ReactiveRedisConnection Maven / Gradle / Ivy

There is a newer version: 3.2.5
Show newest version
/*
 * Copyright 2016-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.data.redis.connection;

import lombok.Data;
import reactor.core.publisher.Mono;

import java.io.Closeable;
import java.nio.ByteBuffer;
import java.util.List;

import org.springframework.data.domain.Range;
import org.springframework.data.domain.Range.Bound;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
 * Redis connection using reactive infrastructure declaring entry points for reactive command execution.
 * 

* {@link ReactiveRedisConnection} is typically implemented by a stateful object that requires to be {@link #close() * closed} once it is no longer required. *

* Commands can be either executed by passing plain arguments like {@code key}, {@code value} or wrapped inside a * command stream. Streaming command execution accepts {@link org.reactivestreams.Publisher} of a particular * {@link Command}. Commands are executed at the time their emission. *

* Arguments are binary-safe by using {@link ByteBuffer} arguments. Expect {@link ByteBuffer} to be consumed by * {@link ReactiveRedisConnection} invocation or during execution. Any {@link ByteBuffer} used as method parameter * should not be altered after invocation. * * @author Christoph Strobl * @author Mark Paluch * @since 2.0 * @see Command * @see CommandResponse * @see KeyCommand */ public interface ReactiveRedisConnection extends Closeable { /* * (non-Javadoc) * @see java.io.Closeable#close() */ @Override default void close() { closeLater().block(); } /** * Asynchronously close the connection and release associated resources. * * @return the {@link Mono} signaling when done. */ Mono closeLater(); /** * Get {@link ReactiveKeyCommands}. * * @return never {@literal null}. */ ReactiveKeyCommands keyCommands(); /** * Get {@link ReactiveStringCommands}. * * @return never {@literal null}. */ ReactiveStringCommands stringCommands(); /** * Get {@link ReactiveNumberCommands} * * @return never {@literal null}. */ ReactiveNumberCommands numberCommands(); /** * Get {@link ReactiveListCommands}. * * @return never {@literal null}. */ ReactiveListCommands listCommands(); /** * Get {@link ReactiveSetCommands}. * * @return never {@literal null}. */ ReactiveSetCommands setCommands(); /** * Get {@link ReactiveZSetCommands}. * * @return never {@literal null}. */ ReactiveZSetCommands zSetCommands(); /** * Get {@link ReactiveHashCommands}. * * @return never {@literal null}. */ ReactiveHashCommands hashCommands(); /** * Get {@link ReactiveGeoCommands} * * @return never {@literal null}. */ ReactiveGeoCommands geoCommands(); /** * Get {@link ReactiveHyperLogLogCommands}. * * @return never {@literal null}. */ ReactiveHyperLogLogCommands hyperLogLogCommands(); /** * Get {@link ReactivePubSubCommands}. * * @return never {@literal null}. * @since 2.1 */ ReactivePubSubCommands pubSubCommands(); /** * Get {@link ReactiveScriptingCommands}. * * @return never {@literal null}. */ ReactiveScriptingCommands scriptingCommands(); /** * Get {@link ReactiveServerCommands}. * * @return never {@literal null}. */ ReactiveServerCommands serverCommands(); /** * Test connection. * * @return {@link Mono} wrapping server response message - usually {@literal PONG}. * @see Redis Documentation: PING */ Mono ping(); /** * Base interface for Redis commands executed with a reactive infrastructure. * * @author Christoph Strobl * @author Mark Paluch */ interface Command { /** * @return the key related to this command. */ @Nullable ByteBuffer getKey(); /** * @return command name as {@link String}. */ default String getName() { return getClass().getSimpleName().replace("Command", "").toUpperCase(); } } /** * {@link Command} for key-bound operations. * * @author Christoph Strobl */ class KeyCommand implements Command { private @Nullable ByteBuffer key; /** * Creates a new {@link KeyCommand} given a {@code key}. * * @param key can be {@literal null}. */ public KeyCommand(@Nullable ByteBuffer key) { this.key = key; } /* * (non-Javadoc) * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() */ @Override public ByteBuffer getKey() { return key; } } /** * {@link Command} for key-bound scan operations like {@code SCAN}, {@code HSCAN}, {@code SSCAN} and {@code * ZSCAN}. * * @author Mark Paluch * @author Christoph Strobl * @since 2.1 */ class KeyScanCommand extends KeyCommand { private final ScanOptions options; private KeyScanCommand(@Nullable ByteBuffer key, ScanOptions options) { super(key); Assert.notNull(options, "ScanOptions must not be null!"); this.options = options; } /** * Creates a new {@link KeyScanCommand} given a {@code key}. * * @param key must not be {@literal null}. * @return a new {@link KeyScanCommand} for {@code key}. */ public static KeyScanCommand key(ByteBuffer key) { return new KeyScanCommand(key, ScanOptions.NONE); } /** * Applies {@link ScanOptions}. Constructs a new command instance with all previously configured properties. * * @param options must not be {@literal null}. * @return a new {@link KeyScanCommand} with {@link ScanOptions} applied. */ public KeyScanCommand withOptions(ScanOptions options) { return new KeyScanCommand(getKey(), options); } /** * Get the {@link ScanOptions} to apply. * * @return never {@literal null}. */ public ScanOptions getOptions() { return options; } } /** * @author Christoph Strobl */ class RangeCommand extends KeyCommand { Range range; /** * Creates a new {@link RangeCommand} given a {@code key} and {@link Range}. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. */ private RangeCommand(ByteBuffer key, Range range) { super(key); this.range = range; } /** * Creates a new {@link RangeCommand} given a {@code key}. * * @param key must not be {@literal null}. * @return a new {@link RangeCommand} for {@code key}. */ public static RangeCommand key(ByteBuffer key) { return new RangeCommand(key, Range.unbounded()); } /** * Applies a {@link Range}. Constructs a new command instance with all previously configured properties. * * @param range must not be {@literal null}. * @return a new {@link RangeCommand} with {@link Range} applied. */ public RangeCommand within(Range range) { Assert.notNull(range, "Range must not be null!"); return new RangeCommand(getKey(), range); } /** * Applies a lower bound to the {@link Range}. Constructs a new command instance with all previously configured * properties. * * @param start * @return a new {@link RangeCommand} with the lower bound applied. */ public RangeCommand fromIndex(long start) { return new RangeCommand(getKey(), Range.of(Bound.inclusive(start), range.getUpperBound())); } /** * Applies an upper bound to the {@link Range}. Constructs a new command instance with all previously configured * properties. * * @param end * @return a new {@link RangeCommand} with the upper bound applied. */ public RangeCommand toIndex(long end) { return new RangeCommand(getKey(), Range.of(range.getLowerBound(), Bound.inclusive(end))); } /** * @return the {@link Range}. */ public Range getRange() { return range; } } /** * Base class for command responses. * * @param command input type. * @param command output type. */ @Data class CommandResponse { private final I input; private final @Nullable O output; /** * @return {@literal true} if the response is present. An absent {@link CommandResponse} maps to Redis * {@literal (nil)}. */ public boolean isPresent() { return true; } } /** * {@link CommandResponse} implementation for {@link Boolean} responses. */ class BooleanResponse extends CommandResponse { public BooleanResponse(I input, Boolean output) { super(input, output); } } /** * {@link CommandResponse} implementation for {@link ByteBuffer} responses. */ class ByteBufferResponse extends CommandResponse { public ByteBufferResponse(I input, @Nullable ByteBuffer output) { super(input, output); } } /** * {@link CommandResponse} implementation for {@link ByteBuffer} responses for absent keys. */ class AbsentByteBufferResponse extends ByteBufferResponse { private final static ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.wrap(new byte[0]); public AbsentByteBufferResponse(I input) { super(input, EMPTY_BYTE_BUFFER); } /* (non-Javadoc) * @see org.springframework.data.redis.connection.ReactiveRedisConnection.CommandResponse#isPresent() */ @Override public boolean isPresent() { return false; } } /** * {@link CommandResponse} implementation for {@link List} responses. */ class MultiValueResponse extends CommandResponse> { public MultiValueResponse(I input, List output) { super(input, output); } } /** * {@link CommandResponse} implementation for {@link Number numeric} responses. */ class NumericResponse extends CommandResponse { public NumericResponse(I input, O output) { super(input, output); } } }