Skip to content

Leverage Spring boot Redis Auto configure logic for RedisConnectionFactory #2502

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Srinivas-Karre opened this issue Feb 13, 2023 · 1 comment
Labels
for: external-project For an external project and not something we can fix

Comments

@Srinivas-Karre
Copy link

Spring boot auto configures RedisConnectionFactory if spring-data-redis exists on classpath and RedisConnectionFactory is initialized in LettuceConnectionConfiguration if Lettuce-core available on classpath.

I've only one Redis store as of now, so leveraging Spring boot auto configuration.

Now I'm adding two redis stores, one redis store used as default and other is used when specified with parameter cacheManager = "secondayCacheManager" in @Cacheable annotation so, application should've capability to cache/cache-get on both redis stores.

To configure both Redis Stores, we've to configure both the primary and secondary RedisConnectionFactory and cacheManager using custom configuration. (because spring doesn't auto configure RedisConnectionFactory if it already exists in any custom configuration)

Now the above is custom configuration and missing lot of logic that is happening while configuring RedisConnectionFactory in LettuceConnectionConfiguration.

Auto configure logic for LettuceConnectionConfiguration is package private so, cannot be called directly from custom configuration.

We would like to leverage the auto configure logic in
LettuceConnectionConfiguration while configuring the custom
RedisConnectionFactory for both primary and secondary redis caches.
Is there a way to achieve this?

Reason being we would like keep the redis connection configurations as it is done by spring boot auto configure.

Currently using below code to configure both the primary and secondary RedisConnectionFactory with Pool configuration and some code copy pasted from LettuceConnectionConfiguration class.

public static LettuceConnectionFactory buildLettuceConnectionFactory(RedisProperties properties, ClientResources clientResources) {
        RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration(properties.getHost(), properties.getPort());
        standaloneConfiguration.setDatabase(properties.getDatabase());
        if (properties.getPassword() != null) {
            standaloneConfiguration.setPassword(RedisPassword.of(properties.getPassword()));
        }
        if (properties.getUsername() != null) {
            standaloneConfiguration.setUsername(properties.getUsername());
        }
        LettucePoolingClientConfiguration poolingClientConfiguration = LettucePoolingClientConfiguration.builder()
            .poolConfig(buildGenericObjectPoolConfig(properties))
            .shutdownTimeout(properties.getLettuce().getShutdownTimeout())
            .clientOptions(createClientOptions(properties))
            .clientResources(clientResources)
            .build();
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(
            standaloneConfiguration, poolingClientConfiguration);
        lettuceConnectionFactory.afterPropertiesSet();

        return lettuceConnectionFactory;
    }

    private static GenericObjectPoolConfig buildGenericObjectPoolConfig(RedisProperties properties) {
        RedisProperties.Pool pool = properties.getLettuce().getPool();
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        if (Objects.nonNull(pool)) {
            poolConfig.setMaxIdle(pool.getMaxIdle());
            poolConfig.setMinIdle(pool.getMinIdle());
            poolConfig.setMaxTotal(pool.getMaxActive());
            poolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis());
        }
        return poolConfig;
    }

    private static ClientOptions createClientOptions(RedisProperties properties) {
        ClientOptions.Builder builder = initializeClientOptionsBuilder(properties);
        Duration connectTimeout = properties.getConnectTimeout();
        if (connectTimeout != null) {
            builder.socketOptions(SocketOptions.builder().connectTimeout(connectTimeout).build());
        }
        return builder.timeoutOptions(TimeoutOptions.enabled()).build();
    }

    private static ClientOptions.Builder initializeClientOptionsBuilder(RedisProperties properties) {
        if (properties.getCluster() != null) {
            ClusterClientOptions.Builder builder = ClusterClientOptions.builder();
            Refresh refreshProperties = properties.getLettuce().getCluster().getRefresh();
            Builder refreshBuilder = ClusterTopologyRefreshOptions.builder()
                .dynamicRefreshSources(refreshProperties.isDynamicRefreshSources());
            if (refreshProperties.getPeriod() != null) {
                refreshBuilder.enablePeriodicRefresh(refreshProperties.getPeriod());
            }
            if (refreshProperties.isAdaptive()) {
                refreshBuilder.enableAllAdaptiveRefreshTriggers();
            }
            return builder.topologyRefreshOptions(refreshBuilder.build());
        }
        return ClientOptions.builder();
    }

I've asked the question here as well:
https://stackoverflow.com/questions/75432050/leverage-spring-boot-redis-auto-configure-logic-for-redisconnectionfactory

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 13, 2023
@mp911de
Copy link
Member

mp911de commented Feb 13, 2023

LettuceConnectionConfiguration is specific to Spring Boot. Generally speaking, once you add multiple data sources, all downstream configuration requires explicit wiring.

Please file your ticket at https://github.com/spring-projects/spring-boot/issues.

@mp911de mp911de closed this as not planned Won't fix, can't repro, duplicate, stale Feb 13, 2023
@mp911de mp911de added for: external-project For an external project and not something we can fix and removed status: waiting-for-triage An issue we've not yet triaged labels Feb 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix
Projects
None yet
Development

No branches or pull requests

3 participants