Skip to content

Commit

Permalink
Add client query parameter to redis connection string
Browse files Browse the repository at this point in the history
  • Loading branch information
mcruzdev committed Sep 24, 2024
1 parent 685cdea commit e90d560
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
import static io.quarkus.vertx.core.runtime.SSLConfigHelper.configurePfxTrustOptions;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Logger;

import org.jboss.logging.Logger;

Expand All @@ -28,6 +30,7 @@
import io.quarkus.tls.TlsConfigurationRegistry;
import io.quarkus.tls.runtime.config.TlsConfigUtils;
import io.smallrye.common.annotation.Identifier;
import io.smallrye.config.common.utils.StringUtil;
import io.vertx.core.Vertx;
import io.vertx.core.net.NetClientOptions;
import io.vertx.core.net.ProxyOptions;
Expand All @@ -40,6 +43,7 @@
*/
public class VertxRedisClientFactory {

private static final Logger LOGGER = Logger.getLogger(VertxRedisClientFactory.class.getName());
public static final String DEFAULT_CLIENT = "<default>";

private static final Logger LOGGER = Logger.getLogger(VertxRedisClientFactory.class);
Expand All @@ -51,18 +55,22 @@ private VertxRedisClientFactory() {
public static Redis create(String name, Vertx vertx, RedisClientConfig config, TlsConfigurationRegistry tlsRegistry) {
RedisOptions options = new RedisOptions();

String clientName = config.clientName().orElse(name);

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());
String connectionString = generateConnectionString(clientName, uri);
options.addConnectionString(connectionString);
}
} 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());
String connectionString = generateConnectionString(clientName, uri);
options.addConnectionString(connectionString);
}
} else {
throw new ConfigurationException("Redis host not configured - you must either configure 'quarkus.redis.hosts` or" +
Expand Down Expand Up @@ -107,6 +115,32 @@ public static Redis create(String name, Vertx vertx, RedisClientConfig config, T
return Redis.createClient(vertx, options);
}

public static String generateConnectionString(String clientName, URI uri) {
var sanitizedClientName = StringUtil.replaceNonAlphanumericByUnderscores(clientName)
.replaceAll("_", "-")
.replaceAll("^-+", "")
.replaceAll("-+$", "");
URI withClientName = addClientParameter(sanitizedClientName, uri);
return withClientName.toString().trim();
}

private static URI addClientParameter(String clientName, URI uri) {
try {
String query = uri.getQuery() == null ? "client=%s".formatted(clientName)
: uri.getQuery().formatted("&client=%s", clientName);
return new URI(
uri.getScheme(),
uri.getAuthority(),
uri.getPath(),
query,
uri.getFragment());
} catch (URISyntaxException e) {
LOGGER.warning("Was not possible to apply the client parameter ('%s') to the redis connection string".formatted(
clientName));
return uri;
}
}

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 @@ -169,6 +169,12 @@ public interface RedisClientConfig {
TlsConfig tls();

/**
* The client name used to identify the connection.
* <p>
* If not set it will try to extract the value from the redis client name.
*/
Optional<String> clientName();

* The name of the TLS configuration to use.
* <p>
* If a name is configured, it uses the configuration from {@code quarkus.tls.<name>.*}
Expand Down Expand Up @@ -203,6 +209,7 @@ default String toDebugString() {
", hashSlotCacheTtl=" + hashSlotCacheTtl() +
", tcp=" + tcp() +
", tls=" + tls() +
", clientName=" + clientName() +
'}';
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class CustomCodecResource {
private final ValueCommands<String, Person> values;

public CustomCodecResource(RedisDataSource ds) {
values = ds.value(Person.class);
this.values = ds.value(Person.class);
}

// synchronous
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.quarkus.redis.it;

import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;

import io.quarkus.redis.client.RedisClientName;
import io.quarkus.redis.datasource.RedisDataSource;
import io.vertx.mutiny.redis.client.Command;

@Path("/quarkus-redis/clients")
@ApplicationScoped
public class RedisClientResource {

private final RedisDataSource ds;
private final RedisDataSource client11;

@Inject
public RedisClientResource(@RedisClientName("quarkiverse") RedisDataSource ds,
@RedisClientName("client11") RedisDataSource client11) {
this.ds = ds;
this.client11 = client11;
}

@GET
@Produces(TEXT_PLAIN)
public String clients() {
// ignore response
return ds.execute(Command.CLIENT, "GETNAME").toString();
}

@GET
@Path("/11")
@Produces(TEXT_PLAIN)
public String client11() {
return client11.execute(Command.CLIENT, "GETNAME").toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,11 @@ quarkus.redis.instance-client.hosts=redis://localhost:6379/5
# use DB 3
quarkus.redis.provided-hosts.hosts-provider-name=test-hosts-provider

quarkus.redis.load-script=starwars.redis
quarkus.redis.load-script=starwars.redis

# client-name
quarkus.redis.quarkiverse.client-name=quarkus
quarkus.redis.quarkiverse.hosts=redis://localhost:6379/10

quarkus.redis.client11.client-name=%#@#% !@#$%¨&*(special
quarkus.redis.client11.hosts=redis://localhost:6379/11
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,14 @@ public void testCustomCodec() {
Assertions.assertEquals(person.firstName, "bob");
Assertions.assertEquals(person.lastName, "MORANE");
}

@Test
public void testClientNames() {
RestAssured.given()
.when()
.get("/quarkus-redis/clients/11")
.then()
.statusCode(Matchers.is(200))
.body(Matchers.is("special"));
}
}

0 comments on commit e90d560

Please sign in to comment.