Skip to content

Commit

Permalink
Add client parameter when creating Vertx Redis client
Browse files Browse the repository at this point in the history
  • Loading branch information
mcruzdev committed Sep 29, 2024
1 parent 2811eec commit ec57afa
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package io.quarkus.redis.deployment.client;

import jakarta.inject.Inject;

import org.assertj.core.api.Assertions;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.redis.client.RedisClientName;
import io.quarkus.redis.datasource.RedisDataSource;
import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.QuarkusTestResource;
import io.vertx.mutiny.redis.client.Response;
import io.vertx.redis.client.Command;

@QuarkusTestResource(RedisTestResource.class)
public class RedisConfigureClientNameTest {

@RegisterExtension
static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class))
.overrideConfigKey("quarkus.redis.my-redis.hosts", "${quarkus.redis.tr}/1")
.overrideConfigKey("quarkus.redis.my-redis.configure-client-name", "true")
.overrideConfigKey("quarkus.redis.my-redis.client-name", "perfect-client-name")
.overrideConfigKey("quarkus.redis.no-configure.hosts", "${quarkus.redis.tr}/2")
.overrideConfigKey("quarkus.redis.no-configure.client-name", "i-am-not-applicable")
.overrideConfigKey("quarkus.redis.no-configure.configure-client-name", "false")
.overrideConfigKey("quarkus.redis.from-annotation.configure-client-name", "true")
.overrideConfigKey("quarkus.redis.from-annotation.hosts", "${quarkus.redis.tr}/3");

@Inject
@RedisClientName("my-redis")
RedisDataSource myRedis;

@Inject
@RedisClientName("no-configure")
RedisDataSource noConfigure;

@Inject
@RedisClientName("from-annotation")
RedisDataSource fromAnnotation;

@Test
void shouldConfigureClientNameCorrectly() {
Response executed = myRedis.execute(Command.CLIENT, "GETNAME");
Assertions.assertThat(executed).isNotNull();
Assertions.assertThat(executed.toString()).isEqualTo("perfect-client-name");
}

@Test
void shouldConfigureFromRedisClientNameAnnotation() {
Response executed = fromAnnotation.execute(Command.CLIENT, "GETNAME");
Assertions.assertThat(executed).isNotNull();
Assertions.assertThat(executed.toString()).isEqualTo("from-annotation");
}

@Test
void shouldNotConfigureClientName() {
Response executed = noConfigure.execute(Command.CLIENT, "GETNAME");
Assertions.assertThat(executed).isNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.spi.CDI;

import org.jboss.logging.Logger;

import io.quarkus.redis.client.RedisClient;
import io.quarkus.redis.client.reactive.ReactiveRedisClient;
import io.quarkus.redis.datasource.ReactiveRedisDataSource;
Expand All @@ -38,7 +40,7 @@
public class RedisClientRecorder {

// Split client and DS recorders

private static final Logger LOGGER = Logger.getLogger(RedisClientRecorder.class);
private final RedisConfig config;
private static final Map<String, RedisClientAndApi> clients = new HashMap<>();
private static final Map<String, ReactiveRedisDataSourceImpl> dataSources = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
import static io.quarkus.vertx.core.runtime.SSLConfigHelper.configurePfxTrustOptions;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;

import org.jboss.logging.Logger;

Expand Down Expand Up @@ -41,6 +45,7 @@
public class VertxRedisClientFactory {

public static final String DEFAULT_CLIENT = "<default>";
public static String NON_RESERVED_URI_PATTERN = "[^a-zA-Z0-9\\-_.~]";

private static final Logger LOGGER = Logger.getLogger(VertxRedisClientFactory.class);

Expand All @@ -51,19 +56,30 @@ private VertxRedisClientFactory() {
public static Redis create(String name, Vertx vertx, RedisClientConfig config, TlsConfigurationRegistry tlsRegistry) {
RedisOptions options = new RedisOptions();

Consumer<Set<URI>> configureOptions = new Consumer<Set<URI>>() {
@Override
public void accept(Set<URI> uris) {
for (URI uri : uris) {
if (config.configureClientName()) {
String client = config.clientName().orElse(name);
String newURI = applyClientQueryParam(client, uri);
options.addConnectionString(newURI);
} else {
options.addConnectionString(uri.toString().trim());
}
}
}
};

List<URI> hosts = new ArrayList<>();
if (config.hosts().isPresent()) {
hosts.addAll(config.hosts().get());
for (URI uri : config.hosts().get()) {
options.addConnectionString(uri.toString().trim());
}
configureOptions.accept(config.hosts().get());
} else if (config.hostsProviderName().isPresent()) {
RedisHostsProvider hostsProvider = findProvider(config.hostsProviderName().get());
Set<URI> computedHosts = hostsProvider.getHosts();
hosts.addAll(computedHosts);
for (URI uri : computedHosts) {
options.addConnectionString(uri.toString());
}
configureOptions.accept(computedHosts);
} else {
throw new ConfigurationException("Redis host not configured - you must either configure 'quarkus.redis.hosts` or" +
" 'quarkus.redis.host-provider-name' and have a bean providing the hosts programmatically.");
Expand Down Expand Up @@ -109,6 +125,26 @@ public static Redis create(String name, Vertx vertx, RedisClientConfig config, T
return Redis.createClient(vertx, options);
}

private static String applyClientQueryParam(String client, URI uri) {

if (client.matches(".*" + NON_RESERVED_URI_PATTERN + ".*")) {
LOGGER.warn("The client query parameter contains reserved URI characters. " +
"This may result in an incorrect client name after URI encoding.");
}

String encodedClient = URLEncoder.encode(client, StandardCharsets.UTF_8);
String query = uri.getQuery() == null ? "client=" + encodedClient
: uri.getQuery() + "&client=" + encodedClient;
try {
return new URI(
uri.getScheme(), uri.getAuthority(), uri.getPath(), query, uri.getFragment()).toString().trim();
} catch (URISyntaxException e) {
LOGGER.warnf("Was not possible to generate a new Redis URL with client query parameter, " +
"the value is: %s", client);
return uri.toString().trim();
}
}

private static void customize(String name, RedisOptions options) {
if (Arc.container() != null) {
List<InstanceHandle<RedisOptionsCustomizer>> customizers = Arc.container().listAll(RedisOptionsCustomizer.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.Optional;
import java.util.Set;

import io.quarkus.redis.client.RedisClientName;
import io.quarkus.runtime.annotations.ConfigDocDefault;
import io.quarkus.runtime.annotations.ConfigDocSection;
import io.quarkus.runtime.annotations.ConfigGroup;
Expand Down Expand Up @@ -197,6 +198,28 @@ public interface RedisClientConfig {
@ConfigDocSection
TlsConfig tls();

/**
* The client name used to identify the connection.
* <p>
* If the {@link RedisClientConfig#configureClientName()} is enabled, and this property is not set
* it will attempt to extract the value from the {@link RedisClientName#value()} annotation.
* <p>
* If the {@link RedisClientConfig#configureClientName()} is enabled, both this property and the
* {@link RedisClientName#value()} must adhere to the pattern '[^a-zA-Z0-9\\-_.~]'.
*/
Optional<String> clientName();

/**
* Whether it should set the client name while connecting with Redis.
* <p>
* This is necessary because Redis only accepts {@code client=my-client-name} query parameter after version 6+.
* <p>
* This property can be used with {@link RedisClientConfig#clientName()} configuration.
*
*/
@WithDefault("false")
Boolean configureClientName();

/**
* The name of the TLS configuration to use.
* <p>
Expand Down Expand Up @@ -232,6 +255,8 @@ default String toDebugString() {
", hashSlotCacheTtl=" + hashSlotCacheTtl() +
", tcp=" + tcp() +
", tls=" + tls() +
", clientName=" + clientName() +
", configureClientName=" + configureClientName() +
'}';
}

Expand Down

0 comments on commit ec57afa

Please sign in to comment.