Skip to content

Commit

Permalink
Skriv feil til Redis per key (#776)
Browse files Browse the repository at this point in the history
  • Loading branch information
bjerga authored Nov 20, 2024
1 parent f37e44d commit 73ce524
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package no.nav.helsearbeidsgiver.felles.rapidsrivers.redis

import kotlinx.serialization.builtins.serializer
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.fromJson
import no.nav.helsearbeidsgiver.utils.json.parseJson
import no.nav.helsearbeidsgiver.utils.json.toJson
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"
private const val KEY_FEIL_POSTFIX = "feil"

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

fun lesResultat(transaksjonId: UUID): JsonElement? = resultatKey(transaksjonId).les()

fun lesAlleMellomlagrede(transaksjonId: UUID): Map<Key, JsonElement> {
val prefix = listOf(keyPrefix.name, transaksjonId.toString()).joinKeySeparator(withPostfix = true)

val keys = Key.entries.map { mellomlagringKey(transaksjonId, it) }

return redis
.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 ->
"Klarte ikke parse redis-verdi.".also {
logger.error(it)
sikkerLogger.error("$it\nvalue=$value", error)
}
null
}
}
return Key.entries
.map { mellomlagringKey(transaksjonId, it) }
.lesAlle { removePrefix(prefix) }
}

fun lesResultat(transaksjonId: UUID): JsonElement? = resultatKey(transaksjonId).les()

fun lesFeil(transaksjonId: UUID): JsonElement? = feilKey(transaksjonId).les()
fun lesAlleFeil(transaksjonId: UUID): Map<Key, String> {
val prefix = listOf(keyPrefix.name, transaksjonId.toString()).joinKeySeparator(withPostfix = true)
val postfix = KEY_PART_SEPARATOR + KEY_FEIL_POSTFIX

return Key.entries
.map { feilKey(transaksjonId, it) }
.lesAlle {
removePrefix(prefix)
.removeSuffix(postfix)
}.mapValues { it.value.fromJson(String.serializer()) }
}

fun skrivMellomlagring(
fun skrivResultat(
transaksjonId: UUID,
key: Key,
value: JsonElement,
) {
mellomlagringKey(transaksjonId, key).skriv(value)
resultatKey(transaksjonId).skriv(value)
}

fun skrivResultat(
fun skrivMellomlagring(
transaksjonId: UUID,
key: Key,
value: JsonElement,
) {
resultatKey(transaksjonId).skriv(value)
mellomlagringKey(transaksjonId, key).skriv(value)
}

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

private fun String.les(): JsonElement? =
Expand All @@ -89,19 +79,56 @@ class RedisStore(
sikkerLogger.debug("Leser fra redis:\n$this -> ${value?.toPretty()}")
}

private fun List<String>.lesAlle(redisKeyToJsonKey: String.() -> String): Map<Key, JsonElement> =
redis
.getAll(this)
.mapKeysNotNull { key ->
key
.redisKeyToJsonKey()
.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 ->
"Klarte ikke parse redis-verdi.".also {
logger.error(it)
sikkerLogger.error("$it\nvalue=$value", error)
}
null
}
}

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

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

private fun mellomlagringKey(
transaksjonId: UUID,
key: Key,
): String = listOf(keyPrefix.name, transaksjonId.toString(), key.toString()).joinKeySeparator()
): String =
listOf(
resultatKey(transaksjonId),
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 feilKey(
transaksjonId: UUID,
key: Key,
): String =
listOf(
mellomlagringKey(transaksjonId, key),
KEY_FEIL_POSTFIX,
).joinKeySeparator()
}

private fun List<String>.joinKeySeparator(withPostfix: Boolean = false): String =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package no.nav.helsearbeidsgiver.felles.rapidsrivers.redis

import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.maps.shouldBeEmpty
import io.kotest.matchers.maps.shouldContainExactly
import io.kotest.matchers.nulls.shouldBeNull
import io.kotest.matchers.shouldBe
import kotlinx.serialization.builtins.serializer
Expand All @@ -27,7 +28,7 @@ class RedisStoreTest :
mockStorageInit =
mapOf(
"$keyPrefix#$transaksjonId" to "\"mango\"",
"$keyPrefix#$transaksjonId#Feilmelding" to "\"papaya\"",
"$keyPrefix#$transaksjonId#${Key.SAK_ID}#feil" to "\"papaya\"",
"$keyPrefix#$transaksjonId#${Key.FNR}" to "\"ananas\"",
"$keyPrefix#$transaksjonId#${Key.ORGNRUNDERENHET}" to "\"kokosnøtt\"",
"$keyPrefix#$transaksjonId#${Key.TILGANG}" to null,
Expand Down Expand Up @@ -113,8 +114,8 @@ class RedisStoreTest :
mapOf(
"$transaksjonId" to "\"banan\"",
"$keyPrefix#$transaksjonId" to "\"mango\"",
"$keyPrefix#$transaksjonId#Feilmelding" to "\"papaya\"",
"$keyPrefix#$transaksjonId#${Key.FNR}" to "\"ananas\"",
"$keyPrefix#$transaksjonId#${Key.SAK_ID}#feil" to "\"papaya\"",
),
),
keyPrefix = keyPrefix,
Expand All @@ -125,7 +126,7 @@ class RedisStoreTest :
redisStore.lesResultat(transaksjonId)?.fromJson(String.serializer()) to "mango"
}

test(RedisStore::lesFeil.name) {
test(RedisStore::lesAlleFeil.name) {
val keyPrefix = RedisPrefix.LagreSelvbestemtIm
val transaksjonId = UUID.randomUUID()

Expand All @@ -136,18 +137,23 @@ class RedisStoreTest :
mockStorageInit =
mapOf(
"$transaksjonId" to "\"banan\"",
"$transaksjonId#Feilmelding" to "\"appelsin\"",
"$transaksjonId#${Key.SAK_ID}#feil" to "\"appelsin\"",
"$keyPrefix#$transaksjonId" to "\"mango\"",
"$keyPrefix#$transaksjonId#Feilmelding" to "\"papaya\"",
"$keyPrefix#$transaksjonId#${Key.FNR}" to "\"ananas\"",
"$keyPrefix#$transaksjonId#${Key.SAK_ID}#feil" to "\"papaya\"",
"$keyPrefix#$transaksjonId#${Key.OPPGAVE_ID}#feil" to "\"gojibær\"",
),
),
keyPrefix = keyPrefix,
)

redisStore.lesFeil(UUID.randomUUID()).shouldBeNull()
redisStore.lesAlleFeil(UUID.randomUUID()).shouldBeEmpty()

redisStore.lesFeil(transaksjonId)?.fromJson(String.serializer()) to "papaya"
redisStore.lesAlleFeil(transaksjonId) shouldContainExactly
mapOf(
Key.SAK_ID to "papaya",
Key.OPPGAVE_ID to "gojibær",
)
}

test(RedisStore::skrivMellomlagring.name) {
Expand All @@ -161,7 +167,7 @@ class RedisStoreTest :
mockStorageInit =
mapOf(
"$keyPrefix#$transaksjonId" to "\"rabarbra\"",
"$keyPrefix#$transaksjonId#Feilmelding" to "\"dragefrukt\"",
"$keyPrefix#$transaksjonId#${Key.SAK_ID}#feil" to "\"dragefrukt\"",
),
),
keyPrefix = keyPrefix,
Expand Down Expand Up @@ -194,6 +200,12 @@ class RedisStoreTest :
Key.INNTEKT to "granateple".toJson(),
Key.JOURNALPOST_ID to "litchi".toJson(),
)

redisStore.lesAlleMellomlagrede(UUID.randomUUID()).shouldBeEmpty()

// Har ikke blitt overskrevet
redisStore.lesResultat(transaksjonId)?.fromJson(String.serializer()) shouldBe "rabarbra"
redisStore.lesAlleFeil(transaksjonId) shouldContainExactly mapOf(Key.SAK_ID to "dragefrukt")
}

test(RedisStore::skrivResultat.name) {
Expand All @@ -207,8 +219,8 @@ class RedisStoreTest :
redisWithMockRedisClient(
mockStorageInit =
mapOf(
"$keyPrefix#$transaksjonId1#Feilmelding" to "\"dragefrukt\"",
"$keyPrefix#$transaksjonId1#${Key.FNR}" to "\"durian\"",
"$keyPrefix#$transaksjonId1#${Key.SAK_ID}#feil" to "\"dragefrukt\"",
"$keyPrefix#$transaksjonId2" to "\"rambutan\"",
),
),
Expand All @@ -229,11 +241,12 @@ class RedisStoreTest :
redisStore.lesResultat(transaksjonId1)?.fromJson(String.serializer()) shouldBe "en kolossal rabarbra"

// Har ikke blitt overskrevet
redisStore.lesFeil(transaksjonId1)?.fromJson(String.serializer()) shouldBe "dragefrukt"
redisStore.lesAlleFeil(transaksjonId1) shouldContainExactly mapOf(Key.SAK_ID to "dragefrukt")
redisStore.lesAlleMellomlagrede(transaksjonId1) shouldContainAllExcludingTempKey mapOf(Key.FNR to "durian".toJson())
redisStore.lesResultat(transaksjonId2)?.fromJson(String.serializer()) shouldBe "rambutan"
}

// TODO test mer
test(RedisStore::skrivFeil.name) {
val keyPrefix = RedisPrefix.InntektSelvbestemt
val transaksjonId = UUID.randomUUID()
Expand All @@ -251,17 +264,32 @@ class RedisStoreTest :
keyPrefix = keyPrefix,
)

redisStore.lesFeil(UUID.randomUUID()).shouldBeNull()
redisStore.lesFeil(transaksjonId).shouldBeNull()
redisStore.lesAlleFeil(transaksjonId).shouldBeEmpty()

redisStore.skrivFeil(transaksjonId, Key.SAK_ID, "dragefrukt")

redisStore.skrivFeil(transaksjonId, "dragefrukt".toJson())
redisStore.lesAlleFeil(transaksjonId) shouldContainExactly mapOf(Key.SAK_ID to "dragefrukt")

redisStore.lesFeil(UUID.randomUUID()).shouldBeNull()
redisStore.lesFeil(transaksjonId)?.fromJson(String.serializer()) shouldBe "dragefrukt"
redisStore.skrivFeil(transaksjonId, Key.OPPGAVE_ID, "gojibær")
redisStore.skrivFeil(transaksjonId, Key.SPINN_INNTEKTSMELDING_ID, "jackfrukt")

redisStore.skrivFeil(transaksjonId, "et lass med dragefrukt".toJson())
redisStore.lesAlleFeil(transaksjonId) shouldContainExactly
mapOf(
Key.SAK_ID to "dragefrukt",
Key.OPPGAVE_ID to "gojibær",
Key.SPINN_INNTEKTSMELDING_ID to "jackfrukt",
)

redisStore.skrivFeil(transaksjonId, Key.SAK_ID, "et lass med dragefrukt")

redisStore.lesAlleFeil(transaksjonId) shouldContainExactly
mapOf(
Key.SAK_ID to "et lass med dragefrukt",
Key.OPPGAVE_ID to "gojibær",
Key.SPINN_INNTEKTSMELDING_ID to "jackfrukt",
)

redisStore.lesFeil(transaksjonId)?.fromJson(String.serializer()) shouldBe "et lass med dragefrukt"
redisStore.lesAlleFeil(UUID.randomUUID()).shouldBeEmpty()

// Har ikke blitt overskrevet
redisStore.lesResultat(transaksjonId)?.fromJson(String.serializer()) shouldBe "rabarbra"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class HentForespoerselService(
val avsenderNavn = steg2.personer[steg0.avsenderFnr]?.navn ?: UKJENT_NAVN
val orgNavn = steg2.orgnrMedNavn[steg1.forespoersel.orgnr] ?: UKJENT_VIRKSOMHET

val feil = redisStore.lesFeil(steg0.transaksjonId)?.fromJson(feilMapSerializer)
val feil = redisStore.lesAlleFeil(steg0.transaksjonId)

val resultJson =
ResultJson(
Expand All @@ -191,7 +191,7 @@ class HentForespoerselService(
orgNavn = orgNavn,
inntekt = steg2.inntekt,
forespoersel = steg1.forespoersel,
feil = feil.orEmpty(),
feil = feil,
).toJson(HentForespoerselResultat.serializer()),
).toJson(ResultJson.serializer())

Expand Down Expand Up @@ -235,11 +235,7 @@ class HentForespoerselService(
}

if (overkommeligFeil != null) {
val gamleFeil = redisStore.lesFeil(fail.transaksjonId)?.fromJson(feilMapSerializer)

val alleFeil = gamleFeil.orEmpty() + mapOf(overkommeligFeil.key to overkommeligFeil.feilmelding)

redisStore.skrivFeil(fail.transaksjonId, alleFeil.toJson(feilMapSerializer))
redisStore.skrivFeil(fail.transaksjonId, overkommeligFeil.key, overkommeligFeil.feilmelding)
redisStore.skrivMellomlagring(fail.transaksjonId, overkommeligFeil.key, overkommeligFeil.defaultVerdi)

val meldingMedDefault =
Expand Down Expand Up @@ -290,9 +286,3 @@ private data class Datafeil(
val feilmelding: String,
val defaultVerdi: JsonElement,
)

private val feilMapSerializer =
MapSerializer(
Key.serializer(),
String.serializer(),
)

0 comments on commit 73ce524

Please sign in to comment.