Skip to content

Commit

Permalink
Merge branch 'main' into DOC-4531-set-examples
Browse files Browse the repository at this point in the history
  • Loading branch information
andy-stark-redis authored Jan 10, 2025
2 parents 60768b8 + a8613e8 commit c3abe0f
Show file tree
Hide file tree
Showing 58 changed files with 2,756 additions and 242 deletions.
1 change: 1 addition & 0 deletions .github/wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ xml
RedisJSON
MkDocs
ClientOptions
ClusterClientOptions
TimeoutOptions
timeoutOptions
ClusterCommand
Expand Down
34 changes: 9 additions & 25 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,57 +1,41 @@
Lettuce 6.5.0 RELEASE NOTES
Lettuce 6.7.0 RELEASE NOTES
==============================

The Redis team is delighted to announce the general availability of Lettuce 6.5.
The Redis team is delighted to announce the general availability of Lettuce 6.7.

Great news, everyone! Lettuce 6.5.0 comes with RedisJSON support enabled.
Great news, everyone! Lettuce 6.7.0 comes with RedisJSON support enabled.
For more on that, please consult with the [RedisJSON documentation](https://redis.io/docs/latest/develop/data-types/json/) and the [Lettuce guide on RedisJSON](https://redis.github.io/lettuce/user-guide/redis-json/).

Lettuce 6 supports Redis 2.6+ up to Redis 7.x. In terms of Java runtime, Lettuce requires
at least Java 8 and works with Java 21.

Thanks to all contributors who made Lettuce 6.4.0 possible.
Thanks to all contributors who made Lettuce 6.7.0 possible.

If you need any support, meet Lettuce at

* GitHub Discussions: https://github.com/lettuce-io/lettuce-core/discussions
* Stack Overflow (Questions): https://stackoverflow.com/questions/tagged/lettuce
* Join the chat at https://discord.gg/redis and look for the "Help:Tools Lettuce" channel
* GitHub Issues (Bug reports, feature requests): https://github.com/lettuce-io/lettuce-core/issues
* Documentation: https://lettuce.io/core/6.5.0.RELEASE/reference/
* Javadoc: https://lettuce.io/core/6.5.0.RELEASE/api/
* Documentation: https://lettuce.io/core/6.7.0.RELEASE/reference/
* Javadoc: https://lettuce.io/core/6.7.0.RELEASE/api/

Commands
--------

* Add `CLUSTER MYSHARDID` in #2920 and `CLUSTER LINKS` in #2986
* Add `CLIENT TRACKINGINFO` in #2862


Enhancements
------------

* Default ClientOptions.timeoutOptions to TimeoutOptions.enabled() (#2927)
* Update completeExceptionally on ClusterCommand using super (#2980)


Fixes
-----
* fix(2971): spublish typo fix (#2972)
* Initialize slots with empty BitSet in RedisClusterNode's constructors (#2341)
* Add defensive copy for Futures allOf() method (#2943)
* fix:deadlock when reentrant exclusive lock (#2961)


Other
-----

* Add badges to the README.md file (#2939)
* Convert wiki to markdown docs (#2944)
* Bump org.jacoco:jacoco-maven-plugin from 0.8.9 to 0.8.12 (#2921)
* Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.5 to 3.3.1 (#2922)
* Bump org.apache.maven.plugins:maven-failsafe-plugin from 3.2.5 to 3.3.1 (#2958)
* Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.7.0 to 3.8.0 (#2957)
* Bump org.apache.maven.plugins:maven-surefire-plugin from 3.3.1 to 3.4.0 (#2968)
* Bump org.hdrhistogram:HdrHistogram from 2.1.12 to 2.2.2 (#2966)
* Bump org.apache.maven.plugins:maven-compiler-plugin from 3.12.1 to 3.13.0 (#2978)
* Bump org.apache.logging.log4j:log4j-bom from 2.17.2 to 2.24.0 (#2988)
* Bump io.netty:netty-bom from 4.1.107.Final to 4.1.113.Final (#2990)
* Suspected change in ubuntu causing CI failures (#2949)

74 changes: 37 additions & 37 deletions docs/advanced-usage.md

Large diffs are not rendered by default.

26 changes: 21 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.5.0.BUILD-SNAPSHOT</version>
<version>6.7.0.BUILD-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Lettuce</name>
Expand Down Expand Up @@ -61,7 +61,7 @@
<kotlinx-coroutines.version>1.5.2</kotlinx-coroutines.version>
<latencyutils.version>2.0.3</latencyutils.version>
<log4j2-version>2.24.0</log4j2-version>
<micrometer.version>1.12.4</micrometer.version>
<micrometer.version>1.14.2</micrometer.version>
<micrometer-tracing.version>1.2.4</micrometer-tracing.version>
<mockito.version>4.9.0</mockito.version>
<netty.version>4.1.115.Final</netty.version>
Expand Down Expand Up @@ -178,7 +178,23 @@
</dependencyManagement>

<dependencies>

<dependency>
<groupId>redis.clients.authentication</groupId>
<artifactId>redis-authx-core</artifactId>
<version>0.1.1-beta1</version>
</dependency>
<dependency>
<groupId>redis.clients.authentication</groupId>
<artifactId>redis-authx-entraid</artifactId>
<version>0.1.1-beta1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.cdimascio</groupId>
<artifactId>dotenv-java</artifactId>
<version>2.2.0</version>
<scope>test</scope>
</dependency>
<!-- Start of core dependencies -->

<dependency>
Expand Down Expand Up @@ -271,7 +287,7 @@
<dependency>
<groupId>io.netty.incubator</groupId>
<artifactId>netty-incubator-transport-native-io_uring</artifactId>
<version>0.0.25.Final</version>
<version>0.0.26.Final</version>
<classifier>linux-x86_64</classifier>
<optional>true</optional>
</dependency>
Expand Down Expand Up @@ -548,7 +564,7 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.20.1</version>
<version>1.20.4</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
137 changes: 137 additions & 0 deletions src/main/java/io/lettuce/authx/TokenBasedRedisCredentialsProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* Copyright 2024, Redis Ltd. and Contributors
* All rights reserved.
*
* Licensed under the MIT License.
*/
package io.lettuce.authx;

import io.lettuce.core.RedisCredentials;
import io.lettuce.core.RedisCredentialsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Sinks;
import redis.clients.authentication.core.Token;
import redis.clients.authentication.core.TokenAuthConfig;
import redis.clients.authentication.core.TokenListener;
import redis.clients.authentication.core.TokenManager;

/**
* A {@link RedisCredentialsProvider} implementation that supports token-based authentication for Redis.
* <p>
* This provider uses a {@link TokenManager} to manage and renew tokens, ensuring that the Redis client can authenticate with
* Redis using a dynamically updated token. This is particularly useful in scenarios where Redis access is controlled via
* token-based authentication, such as when Redis is integrated with an identity provider like EntraID.
* </p>
* <p>
* The provider supports streaming of credentials and automatically emits new credentials whenever a token is renewed. It must
* be used with {@link io.lettuce.core.ClientOptions.ReauthenticateBehavior#ON_NEW_CREDENTIALS} to automatically re-authenticate
* connections whenever new tokens are emitted by the provider.
* </p>
* <p>
* The lifecycle of this provider is externally managed. It should be closed when there are no longer any connections using it,
* to stop the token management process and release resources.
* </p>
*
* @since 6.6
*/
public class TokenBasedRedisCredentialsProvider implements RedisCredentialsProvider, AutoCloseable {

private static final Logger log = LoggerFactory.getLogger(TokenBasedRedisCredentialsProvider.class);

private final TokenManager tokenManager;

private final Sinks.Many<RedisCredentials> credentialsSink = Sinks.many().replay().latest();

private TokenBasedRedisCredentialsProvider(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}

private void init() {

TokenListener listener = new TokenListener() {

@Override
public void onTokenRenewed(Token token) {
String username = token.getUser();
char[] pass = token.getValue().toCharArray();
RedisCredentials credentials = RedisCredentials.just(username, pass);
credentialsSink.tryEmitNext(credentials);
}

@Override
public void onError(Exception exception) {
log.error("Token renew failed!", exception);
}

};

try {
tokenManager.start(listener, false);
} catch (Exception e) {
credentialsSink.tryEmitError(e);
tokenManager.stop();
throw new RuntimeException("Failed to start TokenManager", e);
}
}

/**
* Resolve the latest available credentials as a Mono.
* <p>
* This method returns a Mono that emits the most recent set of Redis credentials. The Mono will complete once the
* credentials are emitted. If no credentials are available at the time of subscription, the Mono will wait until
* credentials are available.
*
* @return a Mono that emits the latest Redis credentials
*/
@Override
public Mono<RedisCredentials> resolveCredentials() {

return credentialsSink.asFlux().next();
}

/**
* Expose the Flux for all credential updates.
* <p>
* This method returns a Flux that emits all updates to the Redis credentials. Subscribers will receive the latest
* credentials whenever they are updated. The Flux will continue to emit updates until the provider is shut down.
*
* @return a Flux that emits all updates to the Redis credentials
*/
@Override
public Flux<RedisCredentials> credentials() {

return credentialsSink.asFlux().onBackpressureLatest(); // Provide a continuous stream of credentials
}

@Override
public boolean supportsStreaming() {
return true;
}

/**
* Stop the credentials provider and clean up resources.
* <p>
* This method stops the TokenManager and completes the credentials sink, ensuring that all resources are properly released.
* It should be called when the credentials provider is no longer needed.
*/
@Override
public void close() {
credentialsSink.tryEmitComplete();
tokenManager.stop();
}

public static TokenBasedRedisCredentialsProvider create(TokenAuthConfig tokenAuthConfig) {
return create(new TokenManager(tokenAuthConfig.getIdentityProviderConfig().getProvider(),
tokenAuthConfig.getTokenManagerConfig()));
}

public static TokenBasedRedisCredentialsProvider create(TokenManager tokenManager) {
TokenBasedRedisCredentialsProvider credentialManager = new TokenBasedRedisCredentialsProvider(tokenManager);
credentialManager.init();
return credentialManager;
}

}
12 changes: 12 additions & 0 deletions src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import java.util.Map;
import java.util.Set;

import static io.lettuce.core.ClientOptions.DEFAULT_JSON_PARSER;
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;
Expand Down Expand Up @@ -93,6 +94,7 @@ public abstract class AbstractRedisAsyncCommands<K, V> implements RedisAclAsyncC
*
* @param connection the connection to operate on
* @param codec the codec for command encoding
* @param parser the implementation of the {@link JsonParser} to use
*/
public AbstractRedisAsyncCommands(StatefulConnection<K, V> connection, RedisCodec<K, V> codec, Mono<JsonParser> parser) {
this.parser = parser;
Expand All @@ -101,6 +103,16 @@ public AbstractRedisAsyncCommands(StatefulConnection<K, V> connection, RedisCode
this.jsonCommandBuilder = new RedisJsonCommandBuilder<>(codec, parser);
}

/**
* Initialize a new instance.
*
* @param connection the connection to operate on
* @param codec the codec for command encoding
*/
public AbstractRedisAsyncCommands(StatefulConnection<K, V> connection, RedisCodec<K, V> codec) {
this(connection, codec, DEFAULT_JSON_PARSER);
}

@Override
public RedisFuture<Set<AclCategory>> aclCat() {
return dispatch(commandBuilder.aclCat());
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import java.util.Set;
import java.util.function.Supplier;

import static io.lettuce.core.ClientOptions.DEFAULT_JSON_PARSER;
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;
Expand Down Expand Up @@ -109,6 +110,7 @@ public abstract class AbstractRedisReactiveCommands<K, V>
*
* @param connection the connection to operate on.
* @param codec the codec for command encoding.
* @param parser the implementation of the {@link JsonParser} to use
*/
public AbstractRedisReactiveCommands(StatefulConnection<K, V> connection, RedisCodec<K, V> codec, Mono<JsonParser> parser) {
this.connection = connection;
Expand All @@ -119,6 +121,16 @@ public AbstractRedisReactiveCommands(StatefulConnection<K, V> connection, RedisC
this.tracingEnabled = clientResources.tracing().isEnabled();
}

/**
* Initialize a new instance.
*
* @param connection the connection to operate on.
* @param codec the codec for command encoding.
*/
public AbstractRedisReactiveCommands(StatefulConnection<K, V> connection, RedisCodec<K, V> codec) {
this(connection, codec, DEFAULT_JSON_PARSER);
}

private EventExecutorGroup getScheduler() {

EventExecutorGroup scheduler = this.scheduler;
Expand Down
Loading

0 comments on commit c3abe0f

Please sign in to comment.