spring-projects / spring-boot

Spring Boot
https://spring.io/projects/spring-boot
Apache License 2.0
74.9k stars 40.62k forks source link

Feature parity between Reactive and Non reactive Spring Session Redis autoconfigurators #42604

Open TMRGZ opened 4 days ago

TMRGZ commented 4 days ago

As noted in the Spring Session configuration documentation, reactive indexed repositories can only be enabled through annotations, which limits the configuration flexibility via application.properties.

Additionally, the auto-configuration classes do not account for important properties such as configureRedisAction and namespace.

Simply adding the equivalent methods resolves this issue, as shown in the following configuration:

@Configuration(proxyBeanMethods = false)
  @ConditionalOnProperty(prefix = "spring.session.redis", name = "repository-type", havingValue = "indexed")
  @Import(RedisIndexedWebSessionConfiguration.class)
  @EnableConfigurationProperties(RedisSessionProperties.class)
  static class IndexedRedisSessionConfiguration {

    @Bean
    @ConditionalOnMissingBean
    ConfigureReactiveRedisAction configureRedisAction(RedisSessionProperties redisSessionProperties) {
      return switch (redisSessionProperties.getConfigureAction()) {
        case NOTIFY_KEYSPACE_EVENTS -> new ConfigureNotifyKeyspaceEventsReactiveAction();
        case NONE -> ConfigureReactiveRedisAction.NO_OP;
      };
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    ReactiveSessionRepositoryCustomizer<ReactiveRedisIndexedSessionRepository> springBootSessionRepositoryCustomizer(
        SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
        ServerProperties serverProperties) {
      return (sessionRepository) -> {
        PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
        map.from(sessionProperties.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout()))
            .to(sessionRepository::setDefaultMaxInactiveInterval);
        map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace);
        map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode);
      };
    }

  }

Additionally, it would be helpful to add a similar check for non-indexed repositories when the cleanup-cron property is enabled.

I can provide a PR if needed

wilkinsona commented 2 days ago

Thanks for the report.

The missing support for spring.session.redis.configure-action looks like an oversight. Support was added to Spring Session in 3.3 to which we upgraded in Spring Boot 3.3. We'll have to discuss this as a team to see if we want to treat adding support as enhancement or as a bug of omission.

As far as I can tell, spring.session.redis.namespace is already supported when using a reactive session repository:

https://github.com/spring-projects/spring-boot/blob/870444887d454e133fe244f24679895bd9bdddee/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisReactiveSessionConfiguration.java#L57

This functionality was added when we started supporting reactive in Spring Boot 2.0.

Can you please clarify what you believe to be missing from the reactive session support beyond spring.session.redis.configure-action?

TMRGZ commented 2 days ago

That config works when the default reactive redis session repository is used, but since to use the indexed one you have to use the @EnableRedisIndexedWebSession annotation it's ignored and uses the configurations provided in the annotation.

I'll clarify that this affects only the reactive indexed repository