add Redis cache and some clean up

- update and cleanup in README.md
- update getIdentity to throw response exception with 401 in JwtService
- update http files to use identity from env
- add cacheable to getIdentityFromDevice in DeviceRegistryService
- add RedisCacheConfiguration
- add CacheProperty
- set up cache property
- set up data redis cache
This commit is contained in:
2024-12-24 05:50:56 +01:00
parent 19f46bd01f
commit 6522809dce
14 changed files with 153 additions and 62 deletions

View File

@@ -1,5 +1,6 @@
package ltd.hlaeja
import ltd.hlaeja.property.CacheProperty
import ltd.hlaeja.property.DeviceConfigurationProperty
import ltd.hlaeja.property.DeviceDataProperty
import ltd.hlaeja.property.DeviceRegistryProperty
@@ -7,8 +8,11 @@ import ltd.hlaeja.property.JwtProperty
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.runApplication
import org.springframework.cache.annotation.EnableCaching
@EnableCaching
@EnableConfigurationProperties(
CacheProperty::class,
DeviceConfigurationProperty::class,
DeviceDataProperty::class,
DeviceRegistryProperty::class,

View File

@@ -0,0 +1,26 @@
package ltd.hlaeja.configuration
import java.time.Duration
import ltd.hlaeja.exception.CacheException
import ltd.hlaeja.property.CacheProperty
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.cache.RedisCacheConfiguration
import org.springframework.data.redis.cache.RedisCacheManager
import org.springframework.data.redis.core.RedisTemplate
@Configuration
class RedisCacheConfiguration(
private val cacheProperty: CacheProperty,
) {
@Bean
fun cacheManager(
redisTemplate: RedisTemplate<String, String>,
): RedisCacheManager = redisTemplate.connectionFactory
?.let { RedisCacheManager.builder(it).cacheDefaults(getRedisCacheConfiguration()).build() }
?: throw CacheException("Redis connection factory is not set")
private fun getRedisCacheConfiguration(): RedisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(cacheProperty.timeToLive))
}

View File

@@ -0,0 +1,23 @@
package ltd.hlaeja.exception
@Suppress("unused")
class CacheException : Exception {
constructor() : super()
constructor(message: String) : super(message)
constructor(cause: Throwable) : super(cause)
constructor(
message: String,
cause: Throwable,
) : super(message, cause)
constructor(
message: String,
cause: Throwable,
enableSuppression: Boolean,
writableStackTrace: Boolean,
) : super(message, cause, enableSuppression, writableStackTrace)
}

View File

@@ -0,0 +1,8 @@
package ltd.hlaeja.property
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties(prefix = "cache")
data class CacheProperty(
val timeToLive: Long,
)

View File

@@ -7,6 +7,7 @@ import java.util.UUID
import ltd.hlaeja.library.deviceRegistry.Identity
import ltd.hlaeja.property.DeviceRegistryProperty
import ltd.hlaeja.util.deviceRegistryIdentityDevice
import org.springframework.cache.annotation.Cacheable
import org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE
import org.springframework.stereotype.Service
import org.springframework.web.ErrorResponseException
@@ -31,6 +32,7 @@ class DeviceRegistryService(
.description("Number of failed device identity calls")
.register(meterRegistry)
@Cacheable(value = ["identity"], key = "#device")
suspend fun getIdentityFromDevice(
device: UUID,
): Identity.Response = try {

View File

@@ -1,13 +1,16 @@
package ltd.hlaeja.service
import io.github.oshai.kotlinlogging.KotlinLogging
import io.jsonwebtoken.JwtException
import io.jsonwebtoken.JwtParser
import io.jsonwebtoken.Jwts
import java.util.UUID
import ltd.hlaeja.library.deviceRegistry.Identity
import ltd.hlaeja.property.JwtProperty
import ltd.hlaeja.util.PublicKeyProvider
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Service
import org.springframework.web.server.ResponseStatusException
private val log = KotlinLogging.logger {}
@@ -23,8 +26,13 @@ class JwtService(
suspend fun getIdentity(
identityToken: String,
): Identity.Response = readIdentity(identityToken)
.let { deviceRegistry.getIdentityFromDevice(it) }
): Identity.Response = try {
readIdentity(identityToken)
.let { deviceRegistry.getIdentityFromDevice(it) }
} catch (e: JwtException) {
log.warn { e.localizedMessage }
throw ResponseStatusException(HttpStatus.UNAUTHORIZED)
}
private suspend fun readIdentity(
identity: String,