Skip to content

Commit

Permalink
Gjør bruken av Redis lettere å lese (#727)
Browse files Browse the repository at this point in the history
* Gjør bruken av Redis lettere å lese

* Update felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/rapidsrivers/redis/RedisStore.kt

Co-authored-by: Magnus Sælensminde <[email protected]>

* Update felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/rapidsrivers/redis/RedisStore.kt

Co-authored-by: Magnus Sælensminde <[email protected]>

* Fjern unødvendig mocking

---------

Co-authored-by: Magnus Sælensminde <[email protected]>
  • Loading branch information
bjerga and magnusae authored Oct 28, 2024
1 parent f99d24c commit e27b3bc
Show file tree
Hide file tree
Showing 30 changed files with 362 additions and 325 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import no.nav.helsearbeidsgiver.felles.json.personMapSerializer
import no.nav.helsearbeidsgiver.felles.json.toJson
import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail
import no.nav.helsearbeidsgiver.felles.rapidsrivers.publish
import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisKey
import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore
import no.nav.helsearbeidsgiver.felles.rapidsrivers.service.Service
import no.nav.helsearbeidsgiver.felles.rapidsrivers.service.ServiceMed2Steg
Expand Down Expand Up @@ -185,7 +184,7 @@ class AktiveOrgnrService(
).toJson(AktiveArbeidsgivere.serializer()),
).toJson(ResultJson.serializer())

redisStore.set(RedisKey.of(steg0.transaksjonId), gyldigResponse)
redisStore.skrivResultat(steg0.transaksjonId, gyldigResponse)
} else {
"Steg 1 er ikke komplett under utførelse av steg 2.".also {
logger.error(it)
Expand Down Expand Up @@ -213,7 +212,7 @@ class AktiveOrgnrService(
failure = feilmelding.toJson(),
).toJson(ResultJson.serializer())

redisStore.set(RedisKey.of(transaksjonId), feilResponse)
redisStore.skrivResultat(transaksjonId, feilResponse)
}

override fun Steg0.loggfelt(): Map<String, String> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import no.nav.helsearbeidsgiver.felles.domene.ResultJson
import no.nav.helsearbeidsgiver.felles.json.personMapSerializer
import no.nav.helsearbeidsgiver.felles.json.toJson
import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail
import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisKey
import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisPrefix
import no.nav.helsearbeidsgiver.felles.rapidsrivers.service.ServiceRiverStateful
import no.nav.helsearbeidsgiver.felles.test.json.lesBehov
Expand Down Expand Up @@ -80,7 +79,7 @@ class AktiveOrgnrServiceTest :
)

verify {
mockRedis.store.set(RedisKey.of(transaksjonId), expectedSuccess)
mockRedis.store.skrivResultat(transaksjonId, expectedSuccess)
}
}

Expand All @@ -105,7 +104,7 @@ class AktiveOrgnrServiceTest :
testRapid.inspektør.size shouldBeExactly 3

verify {
mockRedis.store.set(RedisKey.of(transaksjonId), expectedSuccess)
mockRedis.store.skrivResultat(transaksjonId, expectedSuccess)
}
}

Expand All @@ -130,7 +129,7 @@ class AktiveOrgnrServiceTest :
testRapid.inspektør.size shouldBeExactly 3

verify {
mockRedis.store.set(RedisKey.of(transaksjonId), expectedSuccess)
mockRedis.store.skrivResultat(transaksjonId, expectedSuccess)
}
}

Expand All @@ -156,7 +155,7 @@ class AktiveOrgnrServiceTest :
testRapid.inspektør.size shouldBeExactly 3

verify {
mockRedis.store.set(RedisKey.of(transaksjonId), expectedFailure)
mockRedis.store.skrivResultat(transaksjonId, expectedFailure)
}
}

Expand Down Expand Up @@ -185,7 +184,7 @@ class AktiveOrgnrServiceTest :
)

verify {
mockRedis.store.set(RedisKey.of(transaksjonId), expectedFailure)
mockRedis.store.skrivResultat(transaksjonId, expectedFailure)
}
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package no.nav.helsearbeidsgiver.inntektsmelding.api

import kotlinx.coroutines.delay
import kotlinx.serialization.json.JsonElement
import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisKey
import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore
import no.nav.helsearbeidsgiver.utils.log.sikkerLogger
import java.util.UUID
Expand All @@ -21,7 +20,7 @@ class RedisPoller(
repeat(MAX_RETRIES) {
sikkerLogger.debug("Polling redis: $it time(s) for key $key")

val result = redisStore.get(RedisKey.of(key))
val result = redisStore.lesResultat(key)

if (result != null) {
sikkerLogger.info("Hentet verdi for: '$key' = $result")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ class RedisPollerTest :
}

test("skal finne med tillatt antall forsøk") {
every { mockRedisStore.get(any()) } returnsMany answers(answerOnAttemptNo = 10, answer = dataJson)
every { mockRedisStore.lesResultat(any()) } returnsMany answers(answerOnAttemptNo = 10, answer = dataJson)

val json = redisPoller.hent(key)

json shouldBe dataJson
}

test("skal ikke finne etter maks forsøk") {
every { mockRedisStore.get(any()) } returnsMany answers(answerOnAttemptNo = 11, answer = dataJson)
every { mockRedisStore.lesResultat(any()) } returnsMany answers(answerOnAttemptNo = 11, answer = dataJson)

assertThrows<RedisPollerTimeoutException> {
redisPoller.hent(key)
Expand All @@ -72,7 +72,7 @@ class RedisPollerTest :
""".removeJsonWhitespace()
.parseJson()

every { mockRedisStore.get(any()) } returnsMany answers(answerOnAttemptNo = 1, answer = expectedJson)
every { mockRedisStore.lesResultat(any()) } returnsMany answers(answerOnAttemptNo = 1, answer = expectedJson)

val resultat = redisPoller.hent(key).fromJson(Forespoersel.serializer())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ class RedisConnection(

fun get(key: String): String? = syncCommands.get(key)

internal fun getAll(vararg keys: String): Map<String, String> =
syncCommands
.mget(*keys)
internal fun getAll(keys: List<String>): Map<String, String> {
val keysAsArray = keys.toSet().toTypedArray()
return syncCommands
.mget(*keysAsArray)
.associate { it.key to it.getValueOrElse(null) }
.mapValuesNotNull { it }
}

internal fun set(
key: String,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package no.nav.helsearbeidsgiver.felles.rapidsrivers.redis

import kotlinx.serialization.json.JsonElement
import no.nav.helsearbeidsgiver.felles.Key
import no.nav.helsearbeidsgiver.utils.collection.mapKeysNotNull
import no.nav.helsearbeidsgiver.utils.collection.mapValuesNotNull
import no.nav.helsearbeidsgiver.utils.json.parseJson
import no.nav.helsearbeidsgiver.utils.json.toPretty
import no.nav.helsearbeidsgiver.utils.log.logger
import no.nav.helsearbeidsgiver.utils.log.sikkerLogger
import java.util.UUID

private const val KEY_PART_SEPARATOR = "#"
private const val KEY_FEIL_POSTFIX = "Feilmelding"

class RedisStore(
// class RedisStore<Success : Any, Failure : Any>(
Expand All @@ -17,23 +23,25 @@ class RedisStore(
private val logger = logger()
private val sikkerLogger = sikkerLogger()

internal val keyPartSeparator = "#"

fun get(key: RedisKey): JsonElement? {
val value =
redis.get(key.toStoreKey())
fun lesAlleMellomlagrede(transaksjonId: UUID): Map<Key, JsonElement> {
val prefix = listOf(keyPrefix.name, transaksjonId.toString()).joinKeySeparator(withPostfix = true)

val valueJson = value?.parseJson()

sikkerLogger.debug("Getting from redis: ${key.toStoreKey()} -> ${valueJson?.toPretty()}")
return valueJson
}
val keys = Key.entries.map { mellomlagringKey(transaksjonId, it) }

fun getAll(keys: Set<RedisKey>): Map<String, JsonElement> {
val storeKeys = keys.map { it.toStoreKey() }.toTypedArray()
return redis
.getAll(*storeKeys)
.mapValuesNotNull { value ->
.getAll(keys)
.mapKeysNotNull { key ->
key
.removePrefix(prefix)
.runCatching(Key::fromString)
.getOrElse { error ->
"Feil med nøkkel '$key' i Redis.".also {
logger.error(it)
sikkerLogger.error(it, error)
}
null
}
}.mapValuesNotNull { value ->
value
.runCatching(String::parseJson)
.getOrElse { error ->
Expand All @@ -43,25 +51,65 @@ class RedisStore(
}
null
}
}.mapKeys {
it.key.removePrefix("${keyPrefix.name}$keyPartSeparator")
}.also {
sikkerLogger.debug("Getting all from redis: $it")
}
}

fun set(
key: RedisKey,
fun lesResultat(transaksjonId: UUID): JsonElement? = resultatKey(transaksjonId).les()

fun lesFeil(transaksjonId: UUID): JsonElement? = feilKey(transaksjonId).les()

fun skrivMellomlagring(
transaksjonId: UUID,
key: Key,
value: JsonElement,
) {
sikkerLogger.debug("Setting in redis: ${key.toStoreKey()} -> ${value.toPretty()}")
mellomlagringKey(transaksjonId, key).skriv(value)
}

redis.set(key.toStoreKey(), value.toString())
fun skrivResultat(
transaksjonId: UUID,
value: JsonElement,
) {
resultatKey(transaksjonId).skriv(value)
}

// TODO Skriv feil for hver key separat
fun skrivFeil(
transaksjonId: UUID,
value: JsonElement,
) {
feilKey(transaksjonId).skriv(value)
}

private fun String.les(): JsonElement? =
redis
.get(this)
?.parseJson()
.also { value ->
sikkerLogger.debug("Leser fra redis:\n$this -> ${value?.toPretty()}")
}

private fun String.skriv(value: JsonElement) {
sikkerLogger.debug("Skriver til redis:\n$this -> ${value.toPretty()}")
redis.set(this, value.toString())
}

private fun RedisKey.toStoreKey(): String = listOf(keyPrefix.name).plus(keyParts()).joinToString(separator = keyPartSeparator)
private fun mellomlagringKey(
transaksjonId: UUID,
key: Key,
): String = listOf(keyPrefix.name, transaksjonId.toString(), key.toString()).joinKeySeparator()

private fun resultatKey(transaksjonId: UUID): String = listOf(keyPrefix.name, transaksjonId.toString()).joinKeySeparator()

private fun feilKey(transaksjonId: UUID): String = listOf(keyPrefix.name, transaksjonId.toString(), KEY_FEIL_POSTFIX).joinKeySeparator()
}

private fun List<String>.joinKeySeparator(withPostfix: Boolean = false): String =
joinToString(
separator = KEY_PART_SEPARATOR,
postfix = if (withPostfix) KEY_PART_SEPARATOR else "",
)

enum class RedisPrefix {
AktiveOrgnr,
HentForespoersel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ import no.nav.helsearbeidsgiver.felles.json.les
import no.nav.helsearbeidsgiver.felles.json.toMap
import no.nav.helsearbeidsgiver.felles.json.toPretty
import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail
import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisKey
import no.nav.helsearbeidsgiver.felles.rapidsrivers.river.ObjectRiver
import no.nav.helsearbeidsgiver.felles.utils.Log
import no.nav.helsearbeidsgiver.utils.collection.mapKeysNotNull
import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer
import no.nav.helsearbeidsgiver.utils.json.toPretty
import no.nav.helsearbeidsgiver.utils.log.logger
import no.nav.helsearbeidsgiver.utils.log.sikkerLogger
import java.util.UUID

class ServiceRiverStateless(
override val service: Service,
Expand Down Expand Up @@ -54,15 +51,15 @@ class ServiceRiverStateful<S>(
when (this) {
is DataMelding -> {
dataMap.forEach { (key, data) ->
service.redisStore.set(RedisKey.of(transaksjonId, key), data)
service.redisStore.skrivMellomlagring(transaksjonId, key, data)
}

"Lagret ${dataMap.size} nøkler (med data) i Redis.".also {
logger.info(it)
sikkerLogger.info("$it\n${json.toPretty()}")
}

val meldingMedRedisData = getAllRedisData(transaksjonId) + json
val meldingMedRedisData = service.redisStore.lesAlleMellomlagrede(transaksjonId).plus(json)

service.onData(meldingMedRedisData)
}
Expand All @@ -73,32 +70,14 @@ class ServiceRiverStateful<S>(
sikkerLogger.error("$it Utløsende melding er \n${fail.utloesendeMelding.toPretty()}")
}

val meldingMedRedisData = getAllRedisData(transaksjonId) + json
val meldingMedRedisData = service.redisStore.lesAlleMellomlagrede(transaksjonId).plus(json)

service.onError(meldingMedRedisData, fail)
}
}

return null
}

private fun getAllRedisData(transaksjonId: UUID): Map<Key, JsonElement> {
val allKeys = Key.entries.map { RedisKey.of(transaksjonId, it) }.toSet()
return service.redisStore
.getAll(allKeys)
.mapKeysNotNull { key ->
key
.removePrefix("$transaksjonId${service.redisStore.keyPartSeparator}")
.runCatching(Key::fromString)
.getOrElse { error ->
"Feil med nøkkel '$key' i Redis.".also {
logger.error(it)
sikkerLogger.error(it, error)
}
null
}
}
}
}

sealed class ServiceRiver : ObjectRiver<ServiceMelding>() {
Expand Down
Loading

0 comments on commit e27b3bc

Please sign in to comment.