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

IS-3066: Use valkey-cache #578

Merged
merged 1 commit into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .nais/naiserator-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ spec:
claims:
extra:
- "NAVident"
redis:
valkey:
- instance: cache
access: readwrite
tokenx:
Expand Down
2 changes: 1 addition & 1 deletion .nais/naiserator-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ spec:
claims:
extra:
- "NAVident"
redis:
valkey:
- instance: cache
access: readwrite
tokenx:
Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ Creating a docker image should be as simple as `docker build -t isdialogmote .`

### Cache

This application uses Redis for caching. Redis is deployed automatically on changes to workflow or config on master
branch. For manual deploy, run: `kubectl apply -f .nais/redis-config.yaml`
or `kubectl apply -f .nais/redisexporter.yaml`.
This application uses Aiven Valkey for caching.

### Kafka

Expand Down
20 changes: 10 additions & 10 deletions src/main/kotlin/no/nav/syfo/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import no.nav.syfo.application.ApplicationState
import no.nav.syfo.application.Environment
import no.nav.syfo.application.api.apiModule
import no.nav.syfo.application.api.authentication.getWellKnown
import no.nav.syfo.application.cache.RedisStore
import no.nav.syfo.application.cache.ValkeyStore
import no.nav.syfo.application.database.applicationDatabase
import no.nav.syfo.application.database.databaseModule
import no.nav.syfo.application.isDevGcp
Expand Down Expand Up @@ -76,16 +76,16 @@ fun main() {
kafkaEsyfovarselConfig(environment.kafka)
),
)
val redisConfig = environment.redisConfig
val cache = RedisStore(
val valkeyConfig = environment.valkeyConfig
val cache = ValkeyStore(
JedisPool(
JedisPoolConfig(),
HostAndPort(redisConfig.host, redisConfig.port),
HostAndPort(valkeyConfig.host, valkeyConfig.port),
DefaultJedisClientConfig.builder()
.ssl(redisConfig.ssl)
.user(redisConfig.redisUsername)
.password(redisConfig.redisPassword)
.database(redisConfig.redisDB)
.ssl(valkeyConfig.ssl)
.user(valkeyConfig.valkeyUsername)
.password(valkeyConfig.valkeyPassword)
.database(valkeyConfig.valkeyDB)
.build()
)
)
Expand All @@ -95,7 +95,7 @@ fun main() {
aadAppClient = environment.aadAppClient,
aadAppSecret = environment.aadAppSecret,
aadTokenEndpoint = environment.aadTokenEndpoint,
redisStore = cache,
valkeyStore = cache,
)
val tokendingsClient = TokendingsClient(
tokenxClientId = environment.tokenxClientId,
Expand All @@ -113,7 +113,7 @@ fun main() {
azureAdV2Client = azureAdV2Client,
pdlClientId = environment.pdlClientId,
pdlUrl = environment.pdlUrl,
redisStore = cache,
valkeyStore = cache,
)
val behandlendeEnhetClient = BehandlendeEnhetClient(
azureAdV2Client = azureAdV2Client,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package no.nav.syfo.application

import io.ktor.server.application.*
import no.nav.syfo.application.cache.RedisConfig
import no.nav.syfo.application.cache.ValkeyConfig
import java.net.URI
import java.time.LocalDate

Expand Down Expand Up @@ -29,11 +29,11 @@ data class Environment(
aivenTruststoreLocation = getEnvVar("KAFKA_TRUSTSTORE_PATH"),
aivenKeystoreLocation = getEnvVar("KAFKA_KEYSTORE_PATH"),
),
val redisConfig: RedisConfig = RedisConfig(
redisUri = URI(getEnvVar("REDIS_URI_CACHE")),
redisDB = 7, // se https://github.com/navikt/istilgangskontroll/blob/master/README.md
redisUsername = getEnvVar("REDIS_USERNAME_CACHE"),
redisPassword = getEnvVar("REDIS_PASSWORD_CACHE"),
val valkeyConfig: ValkeyConfig = ValkeyConfig(
valkeyUri = URI(getEnvVar("VALKEY_URI_CACHE")),
valkeyDB = 7, // se https://github.com/navikt/istilgangskontroll/blob/master/README.md
valkeyUsername = getEnvVar("VALKEY_USERNAME_CACHE"),
valkeyPassword = getEnvVar("VALKEY_PASSWORD_CACHE"),
),
val isdialogmoteDbHost: String = getEnvVar("NAIS_DATABASE_ISDIALOGMOTE_ISDIALOGMOTE_DB_HOST"),
val isdialogmoteDbPort: String = getEnvVar("NAIS_DATABASE_ISDIALOGMOTE_ISDIALOGMOTE_DB_PORT"),
Expand Down
14 changes: 0 additions & 14 deletions src/main/kotlin/no/nav/syfo/application/cache/RedisConfig.kt

This file was deleted.

14 changes: 14 additions & 0 deletions src/main/kotlin/no/nav/syfo/application/cache/ValkeyConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package no.nav.syfo.application.cache

import java.net.URI

class ValkeyConfig(
val valkeyUri: URI,
val valkeyDB: Int,
val valkeyUsername: String,
val valkeyPassword: String,
val ssl: Boolean = true
) {
val host: String = valkeyUri.host
val port: Int = valkeyUri.port
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory
import redis.clients.jedis.JedisPool
import redis.clients.jedis.exceptions.JedisConnectionException

class RedisStore(private val jedisPool: JedisPool) {
class ValkeyStore(private val jedisPool: JedisPool) {

private val log: Logger = LoggerFactory.getLogger("no.nav.syfo.application.cache")
val mapper = configuredJacksonMapper()
Expand Down Expand Up @@ -34,7 +34,7 @@ class RedisStore(private val jedisPool: JedisPool) {
try {
jedisPool.resource.use { jedis -> return jedis.get(key) }
} catch (e: JedisConnectionException) {
log.warn("Got connection error when fetching from redis! Continuing without cached value", e)
log.warn("Got connection error when fetching from valkey! Continuing without cached value", e)
return null
}
}
Expand All @@ -53,7 +53,7 @@ class RedisStore(private val jedisPool: JedisPool) {
)
}
} catch (e: JedisConnectionException) {
log.warn("Got connection error when storing in redis! Continue without caching", e)
log.warn("Got connection error when storing in valkey! Continue without caching", e)
}
}
}
12 changes: 6 additions & 6 deletions src/main/kotlin/no/nav/syfo/client/azuread/AzureAdV2Client.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import io.ktor.client.statement.*
import io.ktor.http.*
import no.nav.syfo.application.api.authentication.getConsumerClientId
import no.nav.syfo.application.api.authentication.getNAVIdentFromToken
import no.nav.syfo.application.cache.RedisStore
import no.nav.syfo.application.cache.ValkeyStore
import no.nav.syfo.client.httpClientProxy
import org.slf4j.LoggerFactory

class AzureAdV2Client(
private val aadAppClient: String,
private val aadAppSecret: String,
private val aadTokenEndpoint: String,
private val redisStore: RedisStore,
private val valkeyStore: ValkeyStore,
private val httpClient: HttpClient = httpClientProxy(),
) {

Expand All @@ -29,7 +29,7 @@ class AzureAdV2Client(
val veilederIdent = getNAVIdentFromToken(token)

val cacheKey = "$veilederIdent-$azp-$scopeClientId"
val cachedToken: AzureAdV2Token? = redisStore.getObject(key = cacheKey)
val cachedToken: AzureAdV2Token? = valkeyStore.getObject(key = cacheKey)
return if (cachedToken?.isExpired() == false) {
COUNT_CALL_AZUREAD_TOKEN_OBO_CACHE_HIT.increment()
cachedToken
Expand All @@ -48,7 +48,7 @@ class AzureAdV2Client(
azureAdTokenResponse?.let { tokenResponse ->
val azureAdToken = tokenResponse.toAzureAdV2Token()
COUNT_CALL_AZUREAD_TOKEN_OBO_CACHE_MISS.increment()
redisStore.setObject(
valkeyStore.setObject(
expireSeconds = 3600,
key = cacheKey,
value = azureAdToken,
Expand All @@ -60,7 +60,7 @@ class AzureAdV2Client(

suspend fun getSystemToken(scopeClientId: String): AzureAdV2Token? {
val cacheKey = "${CACHE_AZUREAD_TOKEN_SYSTEM_KEY_PREFIX}$scopeClientId"
val cachedToken = redisStore.getObject<AzureAdV2Token>(key = cacheKey)
val cachedToken = valkeyStore.getObject<AzureAdV2Token>(key = cacheKey)
return if (cachedToken?.isExpired() == false) {
COUNT_CALL_AZUREAD_TOKEN_SYSTEM_CACHE_HIT.increment()
cachedToken
Expand All @@ -76,7 +76,7 @@ class AzureAdV2Client(
azureAdTokenResponse?.let { token ->
val azureAdToken = token.toAzureAdV2Token()
COUNT_CALL_AZUREAD_TOKEN_SYSTEM_CACHE_MISS.increment()
redisStore.setObject(
valkeyStore.setObject(
expireSeconds = 3600,
key = cacheKey,
value = azureAdToken,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import net.logstash.logback.argument.StructuredArguments
import no.nav.syfo.application.cache.RedisStore
import no.nav.syfo.application.cache.ValkeyStore
import no.nav.syfo.client.azuread.AzureAdV2Client
import no.nav.syfo.client.httpClientDefault
import no.nav.syfo.client.tokendings.TokendingsClient
Expand All @@ -21,7 +21,7 @@ class NarmesteLederClient(
private val narmestelederClientId: String,
private val azureAdV2Client: AzureAdV2Client,
private val tokendingsClient: TokendingsClient,
private val cache: RedisStore,
private val cache: ValkeyStore,
private val httpClient: HttpClient = httpClientDefault(),
) {
private val narmesteLederPath = "$narmesteLederBaseUrl$CURRENT_NARMESTELEDER_PATH"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import net.logstash.logback.argument.StructuredArguments
import no.nav.syfo.application.cache.RedisStore
import no.nav.syfo.application.cache.ValkeyStore
import no.nav.syfo.client.azuread.AzureAdV2Client
import no.nav.syfo.client.httpClientDefault
import no.nav.syfo.domain.PersonIdent
Expand All @@ -22,7 +22,7 @@ class OppfolgingstilfelleClient(
private val tokendingsClient: TokendingsClient,
private val isoppfolgingstilfelleClientId: String,
isoppfolgingstilfelleBaseUrl: String,
private val cache: RedisStore,
private val cache: ValkeyStore,
private val httpClient: HttpClient = httpClientDefault()
) {
private val personOppfolgingstilfelleUrl: String =
Expand Down
12 changes: 6 additions & 6 deletions src/main/kotlin/no/nav/syfo/client/pdl/PdlClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import no.nav.syfo.application.cache.RedisStore
import no.nav.syfo.application.cache.ValkeyStore
import no.nav.syfo.client.azuread.AzureAdV2Client
import no.nav.syfo.client.azuread.AzureAdV2Token
import no.nav.syfo.client.httpClientDefault
Expand All @@ -20,23 +20,23 @@ class PdlClient(
private val azureAdV2Client: AzureAdV2Client,
private val pdlClientId: String,
private val pdlUrl: String,
private val redisStore: RedisStore,
private val valkeyStore: ValkeyStore,
private val httpClient: HttpClient = httpClientDefault(),
) {

suspend fun navn(
personIdent: PersonIdent,
): String {
val cacheKey = "$NAVN_CACHE_KEY_PREFIX${personIdent.value}"
val cachedNavn: String? = redisStore.get(key = cacheKey)
val cachedNavn: String? = valkeyStore.get(key = cacheKey)
return if (cachedNavn != null) {
cachedNavn
} else {
val token = azureAdV2Client.getSystemToken(pdlClientId)
?: throw RuntimeException("Failed to send request to PDL: No token was found")
val navn = person(personIdent, token)?.fullName()
?: throw RuntimeException("PDL returned empty navn for given fnr")
redisStore.set(cacheKey, navn, CACHE_EXPIRE_SECONDS)
valkeyStore.set(cacheKey, navn, CACHE_EXPIRE_SECONDS)
navn
}
}
Expand All @@ -46,7 +46,7 @@ class PdlClient(
callId: String,
): Set<PersonIdent> {
val cacheKey = "$FOLKEREG_IDENTER_CACHE_KEY_PREFIX${personIdent.value}"
val cachedIdenter: Set<PersonIdent>? = redisStore.getSetObject(key = cacheKey)
val cachedIdenter: Set<PersonIdent>? = valkeyStore.getSetObject(key = cacheKey)
return if (cachedIdenter != null) {
cachedIdenter
} else {
Expand All @@ -62,7 +62,7 @@ class PdlClient(
} ?: emptySet()
)
}.toSet().also {
redisStore.setObject(cacheKey, it, CACHE_EXPIRE_SECONDS)
valkeyStore.setObject(cacheKey, it, CACHE_EXPIRE_SECONDS)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import net.logstash.logback.argument.StructuredArguments
import no.nav.syfo.application.cache.RedisStore
import no.nav.syfo.application.cache.ValkeyStore
import no.nav.syfo.client.azuread.AzureAdV2Client
import no.nav.syfo.client.httpClientDefault
import no.nav.syfo.client.person.COUNT_CALL_PERSON_KONTAKTINFORMASJON_FAIL
Expand All @@ -18,7 +18,7 @@ import org.slf4j.LoggerFactory

class KontaktinformasjonClient(
private val azureAdV2Client: AzureAdV2Client,
private val cache: RedisStore,
private val cache: ValkeyStore,
private val clientId: String,
baseUrl: String,
private val httpClient: HttpClient = httpClientDefault()
Expand Down
8 changes: 4 additions & 4 deletions src/main/kotlin/no/nav/syfo/cronjob/CronjobModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package no.nav.syfo.cronjob
import io.ktor.server.application.Application
import no.nav.syfo.application.ApplicationState
import no.nav.syfo.application.Environment
import no.nav.syfo.application.cache.RedisStore
import no.nav.syfo.application.cache.ValkeyStore
import no.nav.syfo.application.database.DatabaseInterface
import no.nav.syfo.application.launchBackgroundTask
import no.nav.syfo.brev.arbeidstaker.ArbeidstakerVarselService
Expand Down Expand Up @@ -33,7 +33,7 @@ fun Application.cronjobModule(
applicationState: ApplicationState,
database: DatabaseInterface,
environment: Environment,
cache: RedisStore,
cache: ValkeyStore,
dialogmotestatusService: DialogmotestatusService,
dialogmoterelasjonService: DialogmoterelasjonService,
arbeidstakerVarselService: ArbeidstakerVarselService,
Expand All @@ -43,7 +43,7 @@ fun Application.cronjobModule(
aadAppClient = environment.aadAppClient,
aadAppSecret = environment.aadAppSecret,
aadTokenEndpoint = environment.aadTokenEndpoint,
redisStore = cache,
valkeyStore = cache,
)
val dokarkivClient = DokarkivClient(
azureAdV2Client = azureAdV2Client,
Expand All @@ -54,7 +54,7 @@ fun Application.cronjobModule(
azureAdV2Client = azureAdV2Client,
pdlClientId = environment.pdlClientId,
pdlUrl = environment.pdlUrl,
redisStore = cache,
valkeyStore = cache,
)
val eregClient = EregClient(
baseUrl = environment.eregUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import io.mockk.mockk
import io.mockk.verify
import java.time.LocalDateTime
import kotlinx.coroutines.runBlocking
import no.nav.syfo.application.cache.RedisStore
import no.nav.syfo.application.cache.ValkeyStore
import no.nav.syfo.testhelper.ExternalMockEnvironment
import no.nav.syfo.testhelper.UserConstants.AZUREAD_TOKEN
import no.nav.syfo.testhelper.UserConstants.JWT_AZP
Expand All @@ -25,13 +25,13 @@ class AzureAdClientSpek : Spek({

describe(AzureAdClientSpek::class.java.simpleName) {
val externalMockEnvironment = ExternalMockEnvironment.getInstance()
val cacheMock = mockk<RedisStore>()
val cacheMock = mockk<ValkeyStore>()

val azureAdClient = AzureAdV2Client(
aadAppClient = externalMockEnvironment.environment.aadAppClient,
aadAppSecret = externalMockEnvironment.environment.aadAppSecret,
aadTokenEndpoint = externalMockEnvironment.environment.aadTokenEndpoint,
redisStore = cacheMock,
valkeyStore = cacheMock,
httpClient = externalMockEnvironment.mockHttpClient,
)
val systemTokenCacheKey =
Expand Down
Loading