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

org.eclipse.jnosql.databases.redis.communication.RedisConfiguration Maven / Gradle / Ivy

/*
 *  Copyright (c) 2022 Contributors to the Eclipse Foundation
 *   All rights reserved. This program and the accompanying materials
 *   are made available under the terms of the Eclipse Public License v1.0
 *   and Apache License v2.0 which accompanies this distribution.
 *   The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 *   and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php.
 *
 *   You may elect to redistribute this code under either of these licenses.
 *
 *   Contributors:
 *
 *   Otavio Santana
 */

package org.eclipse.jnosql.databases.redis.communication;

import org.eclipse.jnosql.communication.Configurations;
import org.eclipse.jnosql.communication.Settings;
import org.eclipse.jnosql.communication.SettingsBuilder;
import org.eclipse.jnosql.communication.keyvalue.KeyValueConfiguration;
import redis.clients.jedis.ClientSetInfoConfig;
import redis.clients.jedis.ConnectionPoolConfig;
import redis.clients.jedis.DefaultJedisClientConfig;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisClientConfig;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPooled;
import redis.clients.jedis.JedisSentineled;
import redis.clients.jedis.RedisProtocol;
import redis.clients.jedis.UnifiedJedis;

import java.time.Duration;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.Arrays.asList;

/**
 * The redis implementation of {@link KeyValueConfiguration} whose returns {@link RedisBucketManagerFactory}.
 *
 * @see RedisConfigurations
 */
public final class RedisConfiguration implements KeyValueConfiguration {

    private static final int DEFAULT_PORT = 6379;
    private static final String DEFAULT_HOST = "localhost";

    /**
     * Creates a {@link RedisConfiguration} from map configuration
     *
     * @param configurations the map configuration
     * @return the RedisConfiguration instance
     */
    public RedisBucketManagerFactory getManagerFactory(Map configurations) {
        Objects.requireNonNull(configurations, "configurations is required");
        SettingsBuilder builder = Settings.builder();
        configurations.forEach(builder::put);
        return apply(builder.build());
    }

    @Override
    public RedisBucketManagerFactory apply(Settings settings) {
        Objects.requireNonNull(settings, "settings is required");

        if (settings.keySet()
                .stream()
                .anyMatch(s -> s.startsWith(RedisSentinelConfigurations.SENTINEL.get()))) {
            return applyForSentinel(settings);
        }

        if (settings.keySet()
                .stream()
                .anyMatch(s -> s.startsWith(RedisClusterConfigurations.CLUSTER.get()))) {
            return applyForCluster(settings);
        }

        var simpleJedisConfig = getJedisClientConfig(
                RedisConfigurations.SingleRedisConfigurationsResolver.INSTANCE, settings);

        HostAndPort hostAndPort = getHostAndPort(settings);

        ConnectionPoolConfig connectionPoolConfig = getConnectionPoolConfig(settings);

        UnifiedJedis jedis = new JedisPooled(
                connectionPoolConfig,
                hostAndPort,
                simpleJedisConfig);

        return new DefaultRedisBucketManagerFactory(jedis);
    }

    private HostAndPort getHostAndPort(Settings settings) {
        String localhost = settings
                .getSupplier(asList(RedisConfigurations.HOST, Configurations.HOST))
                .map(Object::toString).orElse(DEFAULT_HOST);

        Integer port = settings.get(RedisConfigurations.PORT)
                .map(Object::toString).map(Integer::parseInt)
                .orElse(DEFAULT_PORT);
        return new HostAndPort(localhost, port);
    }

    private RedisBucketManagerFactory applyForCluster(Settings settings) {

        Set clusterNodes = settings.get(RedisClusterConfigurations.CLUSTER_HOSTS)
                .map(Object::toString)
                .map(h -> h.split(","))
                .map(h -> asList(h).stream().map(HostAndPort::from).collect(Collectors.toSet()))
                .orElseThrow(() -> new IllegalArgumentException("The cluster nodes are required"));

        JedisClientConfig clientConfig = getJedisClientConfig(
                RedisClusterConfigurations.ClusterConfigurationsResolver.INSTANCE, settings);

        int maxAttempts = settings.get(RedisClusterConfigurations.CLUSTER_MAX_ATTEMPTS)
                .map(Object::toString).map(Integer::parseInt)
                .orElse(JedisCluster.DEFAULT_MAX_ATTEMPTS);

        Duration maxTotalRetriesDuration = settings
                .get(RedisClusterConfigurations.CLUSTER_MAX_TOTAL_RETRIES_DURATION)
                .map(Object::toString).map(Duration::parse)
                .orElse(Duration.ofMillis((long) clientConfig.getSocketTimeoutMillis() * maxAttempts));

        ConnectionPoolConfig poolConfig = getConnectionPoolConfig(settings);

        JedisCluster jedis = new JedisCluster(
                clusterNodes,
                clientConfig,
                maxAttempts,
                maxTotalRetriesDuration,
                poolConfig);
        return new DefaultRedisBucketManagerFactory(jedis);
    }

    private RedisBucketManagerFactory applyForSentinel(Settings settings) {

        String masterName = settings.get(RedisSentinelConfigurations.SENTINEL_MASTER_NAME)
                .map(Object::toString)
                .orElseThrow(() -> new IllegalArgumentException("The sentinel master name is required"));

        Set hostAndPorts = settings.get(RedisSentinelConfigurations.SENTINEL_HOSTS)
                .map(Object::toString)
                .map(h -> h.split(","))
                .map(h -> asList(h).stream().map(HostAndPort::from).collect(Collectors.toSet()))
                .orElseThrow(() -> new IllegalArgumentException("The sentinel hosts are required"));

        ConnectionPoolConfig connectionPoolConfig = getConnectionPoolConfig(settings);

        var masterJedisClientConfig = getJedisClientConfig(
                RedisSentinelConfigurations.SentinelMasterConfigurationsResolver.INSTANCE,settings);

        var slaveJedisClientConfig = getJedisClientConfig(
                RedisSentinelConfigurations.SentinelMasterConfigurationsResolver.INSTANCE, settings);

        JedisSentineled jedis = new JedisSentineled(masterName,
                masterJedisClientConfig,
                connectionPoolConfig,
                hostAndPorts,
                slaveJedisClientConfig);

        return new DefaultRedisBucketManagerFactory(jedis);
    }

    private JedisClientConfig getJedisClientConfig(RedisConfigurationsResolver resolver, Settings settings) {

        DefaultJedisClientConfig.Builder builder = DefaultJedisClientConfig.builder();

        settings.get(resolver.connectionTimeoutSupplier())
                .map(Object::toString).map(Integer::parseInt)
                .ifPresent(builder::connectionTimeoutMillis);

        settings.get(resolver.socketTimeoutSupplier())
                .map(Object::toString).map(Integer::parseInt)
                .ifPresent(builder::socketTimeoutMillis);

        settings.get(resolver.clientNameSupplier())
                .map(Object::toString)
                .ifPresent(builder::clientName);

        settings.get(resolver.userSupplier())
                .map(Object::toString)
                .ifPresent(builder::user);

        settings.get(resolver.passwordSupplier())
                .map(Object::toString)
                .ifPresent(builder::password);

        settings.get(resolver.timeoutSupplier())
                .map(Object::toString).map(Integer::parseInt)
                .ifPresent(builder::timeoutMillis);

        settings.get(resolver.sslSupplier())
                .map(Object::toString).map(Boolean::parseBoolean)
                .ifPresent(builder::ssl);

        settings.get(resolver.redisProtocolSupplier())
                .map(Object::toString).map(RedisProtocol::valueOf)
                .ifPresent(builder::protocol);

        settings.get(resolver.clientsetInfoConfigLibNameSuffixSupplier())
                .map(Object::toString)
                .ifPresentOrElse(
                        libNameSuffix -> builder.clientSetInfoConfig(new ClientSetInfoConfig(libNameSuffix)),
                        () -> settings.get(resolver.clientsetInfoConfigDisabled())
                                .map(Object::toString)
                                .map(Boolean::parseBoolean)
                                .map(disabled -> disabled ? ClientSetInfoConfig.DISABLED : ClientSetInfoConfig.DEFAULT)
                                .ifPresent(builder::clientSetInfoConfig));

        return builder.build();
    }

    private ConnectionPoolConfig getConnectionPoolConfig(Settings settings) {

        ConnectionPoolConfig poolConfig = new ConnectionPoolConfig();

        settings.get(RedisConfigurations.MAX_TOTAL)
                .map(Object::toString).map(Integer::parseInt)
                .ifPresent(poolConfig::setMaxTotal);

        settings.get(RedisConfigurations.MAX_IDLE)
                .map(Object::toString).map(Integer::parseInt)
                .ifPresent(poolConfig::setMaxIdle);

        settings.get(RedisConfigurations.MIN_IDLE)
                .map(Object::toString).map(Integer::parseInt)
                .ifPresent(poolConfig::setMinIdle);

        settings.get(RedisConfigurations.MAX_WAIT_MILLIS)
                .map(Object::toString).map(Integer::parseInt)
                .ifPresent(poolConfig::setMaxWaitMillis);

        return poolConfig;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy