Skip to content
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

Redis Keyspace configuration not working as expected #3109

Open
felixwiemuth opened this issue Feb 18, 2025 · 0 comments
Open

Redis Keyspace configuration not working as expected #3109

felixwiemuth opened this issue Feb 18, 2025 · 0 comments
Assignees
Labels
status: waiting-for-triage An issue we've not yet triaged

Comments

@felixwiemuth
Copy link

I am trying to set up a Redis repository with programmatic keyspaces configuration according to https://docs.spring.io/spring-data/redis/reference/redis/redis-repositories/keyspaces.html

I would like to load the timeToLive from a configuration properties.

Problem

Here is the attempt:

@Configuration
@EnableRedisRepositories // NOT PROVIDED because using RedisMappingContext: (keyspaceConfiguration = KeyspaceConfig::class)
class RedisRepositoryConfig(
    val myConfigurationProperties: MyConfigurationProperties
) {
    @Bean
    fun redisTemplate(redisConnectionFactory: RedisConnectionFactory?): RedisTemplate<*, *> {
        val template = RedisTemplate<ByteArray?, ByteArray?>()
        template.connectionFactory = redisConnectionFactory
        return template
    }

    @Bean
    fun keyValueMappingContext() =
        RedisMappingContext(
            MappingConfiguration(IndexConfiguration(), KeyspaceConfig(
                ttl = myConfigurationProperties.redisTTLSeconds.also { println("Creating KeyspaceConfig with TTL=$it") }
            ))
        )
}

// It does not make a difference whether this class is defined within the RedisRepositoryConfig or not
class KeyspaceConfig(
    val ttl: Long,
) : KeyspaceConfiguration() {
    init {
        println("KeyspaceConfig constructor called with TTL=$ttl")
    }
    override fun initialConfiguration(): Iterable<KeyspaceSettings> =
        listOf(
            KeyspaceSettings(MyData::class.java, "MyHash").apply {
                timeToLive = ttl.also { println("initialConfiguration(): TTL property is $ttl") }
            }
        )
}

@RedisHash // This annotation seems still needed
data class MyData(
    @Id
    val resourceId: String,
    val data: String
)

As opposed to the documentation, the KeyspaceSettings are not static, so we have to pass or access the configuration somehow.

  • I tried the timeToLivePropertyName = "my.config.redis-ttl-seconds" field in KeyspaceSettings, but it did not have any effect.
  • I tried injecting the MyConfigurationProperties in the KeyspaceConfig constructor (and using @EnableRedisRepositories(keyspaceConfiguration = KeyspaceConfig::class)) , but that doesn't work
  • So I tried instead passing the value in the constructor (as shown above), in the keyValueMappingContext() bean, but it doesn't work as expected, see below

Running the application results in the following output:

Creating KeyspaceConfig with TTL=5
initialConfiguration(): TTL property is 0
KeyspaceConfig constructor called with TTL=5

This shows that KeyspaceConfig is instantiated from elsewhere, and that instance is used to call initialConfiguration() on, instead of the one that is constructed in keyValueMappingContext(), which I would expect.

Workaround

If not declaring a separate KeyspaceConfig class, but instead implement a KeyspaceConfiguration on-the-fly, it works:

    @Bean
    fun keyValueMappingContext() =
        RedisMappingContext(
            MappingConfiguration(IndexConfiguration(), object : KeyspaceConfiguration() {
                override fun initialConfiguration(): Iterable<KeyspaceSettings> =
                    listOf(
                        KeyspaceSettings(MyData::class.java, "MyHash").apply {
                            timeToLive = myConfigurationProperties.redisTTLSeconds.also { println("initialConfiguration(): TTL is $it") }
                        }
                    )
            }
        ))

Output:

initialConfiguration(): TTL is 5

Issues

  • Why does it behave in the way it does, and is this correct?
  • Can the documentation be updated to show how to properly use KeyspaceConfig when one needs to load properties dynamically or from configuration properties?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

No branches or pull requests

3 participants