Skip to content

Commit 0b49821

Browse files
committed
#1039 Redis Cache configuration
1 parent 288724b commit 0b49821

File tree

7 files changed

+110
-40
lines changed

7 files changed

+110
-40
lines changed

ontrack-model/src/main/java/net/nemerosa/ontrack/model/settings/SecuritySettings.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import net.nemerosa.ontrack.model.form.YesNo
1212
* @property isGrantProjectParticipationToAll `true` when all authenticated users have a participant access to all projects.
1313
*/
1414
@APIDescription("General security settings")
15-
class SecuritySettings(
15+
data class SecuritySettings(
1616
@get:JsonProperty("grantProjectViewToAll")
1717
@APIDescription("Grants project view to all")
1818
val isGrantProjectViewToAll: Boolean,

ontrack-repository-impl/src/main/java/net/nemerosa/ontrack/repository/PropertyJdbcRepository.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import net.nemerosa.ontrack.model.structure.ProjectEntityType
88
import net.nemerosa.ontrack.model.structure.PropertySearchArguments
99
import net.nemerosa.ontrack.repository.support.AbstractJdbcRepository
1010
import org.apache.commons.lang3.StringUtils
11-
import org.springframework.cache.annotation.CacheEvict
12-
import org.springframework.cache.annotation.Cacheable
1311
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource
1412
import org.springframework.stereotype.Repository
1513
import java.lang.String.format
@@ -36,7 +34,6 @@ class PropertyJdbcRepository(
3634
).isNotEmpty()
3735
}
3836

39-
@Cacheable(cacheNames = ["properties"], key = "#typeName + #entityType.name() + #entityId.value")
4037
override fun loadProperty(typeName: String, entityType: ProjectEntityType, entityId: ID): TProperty? {
4138
return getFirstItem(
4239
String.format(
@@ -47,7 +44,6 @@ class PropertyJdbcRepository(
4744
) { rs, rowNum -> toProperty(rs) }
4845
}
4946

50-
@CacheEvict(cacheNames = ["properties"], key = "#typeName + #entityType.name() + #entityId.value")
5147
override fun saveProperty(typeName: String, entityType: ProjectEntityType, entityId: ID, data: JsonNode) {
5248
val params = params("type", typeName).addValue("entityId", entityId.value)
5349
// Any previous value?
@@ -78,7 +74,6 @@ class PropertyJdbcRepository(
7874
}// Creation
7975
}
8076

81-
@CacheEvict(cacheNames = ["properties"], key = "#typeName + #entityType.name() + #entityId.value")
8277
override fun deleteProperty(typeName: String, entityType: ProjectEntityType, entityId: ID): Ack {
8378
return Ack.one(
8479
namedParameterJdbcTemplate!!.update(
Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,48 @@
11
package net.nemerosa.ontrack.service
22

3+
import net.nemerosa.ontrack.common.Caches
4+
import net.nemerosa.ontrack.extension.api.CacheConfigExtension
5+
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer
36
import org.springframework.cache.annotation.EnableCaching
7+
import org.springframework.context.annotation.Bean
48
import org.springframework.context.annotation.Configuration
9+
import org.springframework.data.redis.cache.RedisCacheConfiguration
10+
import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair
11+
import java.time.Duration
512

613
@Configuration
714
@EnableCaching
8-
class CacheConfig
15+
class CacheConfig {
16+
17+
@Bean
18+
fun redisCacheManagerBuilderCustomizer(
19+
cacheConfigExtensions: List<CacheConfigExtension>,
20+
) = RedisCacheManagerBuilderCustomizer { builder ->
21+
// Core caches
22+
builder.withCacheConfiguration(
23+
Caches.SETTINGS,
24+
RedisCacheConfiguration
25+
.defaultCacheConfig(null)
26+
.entryTtl(Duration.ofHours(1))
27+
.serializeValuesWith(
28+
SerializationPair.fromSerializer(
29+
TypedJsonRedisSerializer.instance
30+
)
31+
)
32+
)
33+
// Extensions
34+
cacheConfigExtensions.forEach { extension ->
35+
extension.caches.forEach { (name, config) ->
36+
RedisCacheConfiguration
37+
.defaultCacheConfig(null)
38+
.entryTtl(config.ttl)
39+
.serializeValuesWith(
40+
SerializationPair.fromSerializer(
41+
TypedJsonRedisSerializer.instance
42+
)
43+
)
44+
}
45+
}
46+
}
47+
48+
}

ontrack-service/src/main/java/net/nemerosa/ontrack/service/CacheConfigCustomizer.kt

Lines changed: 0 additions & 33 deletions
This file was deleted.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package net.nemerosa.ontrack.service
2+
3+
import com.fasterxml.jackson.databind.JsonNode
4+
import net.nemerosa.ontrack.json.*
5+
import org.springframework.data.redis.serializer.RedisSerializer
6+
7+
class TypedJsonRedisSerializer private constructor() : RedisSerializer<Any> {
8+
9+
companion object {
10+
val instance = TypedJsonRedisSerializer()
11+
}
12+
13+
override fun serialize(t: Any?): ByteArray? = if (t != null) {
14+
val data = TypedJson(
15+
type = t::class.java.name,
16+
value = t.asJson(),
17+
)
18+
data.asJson().asJsonString().toByteArray(Charsets.UTF_8)
19+
} else {
20+
null
21+
}
22+
23+
override fun deserialize(bytes: ByteArray?): Any? = if (bytes != null) {
24+
val data = bytes.toString(Charsets.UTF_8).parseAsJson().parse<TypedJson>()
25+
val type = Class.forName(data.type)
26+
JsonUtils.parse(data.value, type)
27+
} else {
28+
null
29+
}
30+
31+
private data class TypedJson(
32+
val type: String,
33+
val value: JsonNode,
34+
)
35+
36+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package net.nemerosa.ontrack.service
2+
3+
import net.nemerosa.ontrack.model.settings.SecuritySettings
4+
import org.junit.jupiter.api.Test
5+
import kotlin.test.assertEquals
6+
7+
internal class TypedJsonRedisSerializerTest {
8+
9+
@Test
10+
fun `Serialization and deserialization`() {
11+
val serializer = TypedJsonRedisSerializer.instance
12+
val settings = SecuritySettings(
13+
isGrantProjectViewToAll = false,
14+
isGrantProjectParticipationToAll = false,
15+
builtInAuthenticationEnabled = false,
16+
)
17+
val loaded = serializer.deserialize(serializer.serialize(settings))
18+
assertEquals(settings, loaded)
19+
}
20+
21+
@Test
22+
fun `Serialization and deserialization for null`() {
23+
val serializer = TypedJsonRedisSerializer.instance
24+
val loaded = serializer.deserialize(serializer.serialize(null))
25+
assertEquals(null, loaded)
26+
}
27+
28+
}

ontrack-ui/src/main/resources/config/application.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ spring:
1515
# Default profile
1616
profiles:
1717
default: prod
18+
# Cache configuration
19+
cache:
20+
redis:
21+
enable-statistics: true
1822

1923
# Compression of web resources
2024
server:

0 commit comments

Comments
 (0)