I have a kotlin spring data application with redis caching. I want to clean a Redis database and use redisConnectionFactory.connection.serverCommands().flushAll()
command for it. When I run unit tests individually, everything works without any problems. But when I try to run all the tests in the application (there are about 200 of them) or even tests from any class, then after passing 8 tests everything freezes on the command redisConnectionFactory.connection.serverCommands().flushAll()
(I added logs for debugging, I understood this from it). It’s no use waiting, I have to stop the tests. There is no dependency on tests; this can be reproduced for different classes with different tests.
Perhaps someone has encountered this and can at least give me a hint? Or if someone can give me advice on how to solve my problem of clearing the cache in a different way, I will also be very grateful.
@SpringBootTest
@ExtendWith(SpringExtension::class)
@Import(TestChannelBinderConfiguration::class)
@ContextConfiguration(initializers = [RedisInitializer::class])
@RecordApplicationEvents
abstract class AbstractIntegrationTest {
@Autowired
protected lateinit var redisConnectionFactory: RedisConnectionFactory
@AfterEach
fun clean() {
redisConnectionFactory.connection.serverCommands().flushAll()
}
}
RedisInitializer:
class RedisInitializer : ApplicationContextInitializer<ConfigurableApplicationContext> {
override fun initialize(context: ConfigurableApplicationContext) {
TestPropertyValues.of(
"spring.redis.host=" + REDIS_CONTAINER.host,
"spring.redis.port=" + REDIS_CONTAINER.getMappedPort(REDIS_PORT)
).applyTo(context.environment)
}
companion object {
private const val REDIS_PORT = 6379
private val IMAGE_NAME = DockerImageName.parse("redis:6.2-alpine")
var REDIS_CONTAINER: GenericContainer<*> = GenericContainer<Nothing>(IMAGE_NAME)
.withExposedPorts(REDIS_PORT)
init {
REDIS_CONTAINER.start()
}
}
}
RedisConfig:
@Configuration
@EnableCaching
class RedisConfig(
val redisProperties: RedisProperties
) {
@Bean
fun redisTemplate(connectionFactory: RedisConnectionFactory): RedisTemplate<String, Any> =
RedisTemplate<String, Any>().apply {
setConnectionFactory(connectionFactory)
setDefaultSerializer(StringRedisSerializer())
setValueSerializer(redisSerializer())
}
@Bean
fun redisSerializer(): RedisSerializer<Any> {
val objectMapper = ObjectMapper().apply {
setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY)
}
return Jackson2JsonRedisSerializer(Any::class.java)
.apply {
setObjectMapper(objectMapper)
}
}
@Bean
fun jedisConnectionFactory(): RedisConnectionFactory {
val jedisConnectionFactory = if (redisProperties.sentinel != null) {
JedisConnectionFactory(getSentinelConfiguration())
} else {
JedisConnectionFactory(getStandaloneConfiguration())
}
jedisConnectionFactory.afterPropertiesSet()
return jedisConnectionFactory
}
private fun getSentinelConfiguration(): RedisSentinelConfiguration {
val sentinelConfiguration = RedisSentinelConfiguration()
sentinelConfiguration.setMaster(redisProperties.sentinel.master)
sentinelConfiguration.password = RedisPassword.of(redisProperties.password)
sentinelConfiguration.sentinelPassword = RedisPassword.of(redisProperties.sentinel.password)
sentinelConfiguration.setSentinels(
redisProperties.sentinel.nodes.stream().map { node: String ->
val nodeConf = node.split(":").toTypedArray()
RedisNode(nodeConf[0], nodeConf[1].toInt())
}.collect(Collectors.toList())
)
return sentinelConfiguration
}
/**
* Standalone is used only in integration tests
* when raising the application context and connecting
* to the Redis docker image from the test container.
*/
private fun getStandaloneConfiguration(): RedisStandaloneConfiguration {
val configuration = RedisStandaloneConfiguration()
configuration.hostName = redisProperties.host
configuration.port = redisProperties.port
configuration.password = RedisPassword.of(redisProperties.password)
return configuration
}
}
2
Answers
I replaced
RedisConnectionFactory
withRedisTemplate
and it helped me:This command
redisConnectionFactory.connection.serverCommands().flushAll()
should exhaust connection pool. That’s why you have successfully run only 8 times (apparently pool config have at max 8 connections)How about that:
It guaranties connections will be released.