Skip to content

Commit

Permalink
Merge branch 'main' into dev/fjern-behov-lagre-eim
Browse files Browse the repository at this point in the history
  • Loading branch information
bjerga committed Oct 31, 2024
2 parents a2d93aa + a5e382c commit 0761ae2
Show file tree
Hide file tree
Showing 35 changed files with 738 additions and 302 deletions.
4 changes: 4 additions & 0 deletions config/notifikasjon/dev-gcp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ env:
value: "https://arbeidsgiver.intern.dev.nav.no"
- name: REDIS_URL
value: redis://helsearbeidsgiver-redis.helsearbeidsgiver.svc.cluster.local:6379/0
- name: OPPGAVEPAAMINNELSER_AKTIVERT
value: "true"
- name: TID_MELLOM_OPPGAVEOPPRETTELSE_OG_PAAMINNELSE
value: "PT10M"
apps:
- name: helsearbeidsgiver-redis
- name: notifikasjon-produsent-api
Expand Down
4 changes: 4 additions & 0 deletions config/notifikasjon/prod-gcp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ env:
value: "https://arbeidsgiver.nav.no"
- name: REDIS_URL
value: redis://helsearbeidsgiver-redis.helsearbeidsgiver.svc.cluster.local:6379/0
- name: OPPGAVEPAAMINNELSER_AKTIVERT
value: "false"
- name: TID_MELLOM_OPPGAVEOPPRETTELSE_OG_PAAMINNELSE
value: "P28D"
apps:
- name: helsearbeidsgiver-redis
- name: notifikasjon-produsent-api
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.github.navikt.tbd_libs.rapids_and_rivers.JsonMessage
import com.github.navikt.tbd_libs.rapids_and_rivers.River
import com.github.navikt.tbd_libs.rapids_and_rivers_api.MessageContext
import com.github.navikt.tbd_libs.rapids_and_rivers_api.RapidsConnection
import kotlinx.serialization.json.JsonElement
import no.nav.hag.utils.bakgrunnsjobb.Bakgrunnsjobb
import no.nav.hag.utils.bakgrunnsjobb.BakgrunnsjobbRepository
import no.nav.hag.utils.bakgrunnsjobb.BakgrunnsjobbStatus
Expand All @@ -13,11 +14,9 @@ import no.nav.helsearbeidsgiver.felles.Key
import no.nav.helsearbeidsgiver.felles.json.toJson
import no.nav.helsearbeidsgiver.felles.json.toMap
import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail
import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.ModelUtils.toFailOrNull
import no.nav.helsearbeidsgiver.inntektsmelding.feilbehandler.prosessor.FeilProsessor
import no.nav.helsearbeidsgiver.utils.json.fromJson
import no.nav.helsearbeidsgiver.utils.json.parseJson
import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer
import no.nav.helsearbeidsgiver.utils.json.toJson
import no.nav.helsearbeidsgiver.utils.json.toPretty
import no.nav.helsearbeidsgiver.utils.log.sikkerLogger
Expand Down Expand Up @@ -62,23 +61,37 @@ class FeilLytter(
context: MessageContext,
) {
sikkerLogger.info("Mottok feil: ${packet.toJson().parseJson().toPretty()}")
val fail = toFailOrNull(packet.toJson().parseJson().toMap())
val fail = packet.toJson().parseJson().toFailOrNull()
if (fail == null) {
sikkerLogger.warn("Kunne ikke parse feil-objekt, ignorerer...")
return
}
if (behovSkalHaandteres(fail) || eventSkalHaandteres(fail)) {

val utloesendeMelding = fail.utloesendeMelding.toMap()
if (behovSkalHaandteres(utloesendeMelding) || eventSkalHaandteres(utloesendeMelding)) {
// slå opp transaksjonID. Hvis den finnes, kan det være en annen feilende melding i samme transaksjon (forskjelig behov): Lagre i så fall
// med egen id. Denne id vil så sendes med som ny transaksjonID ved rekjøring..
val jobbId = fail.transaksjonId
val eksisterendeJobb = repository.getById(jobbId)
if (eksisterendeJobb != null) {
if (fail.utloesendeMelding.toMap()[Key.BEHOV] != eksisterendeJobb.data.parseJson().toMap()[Key.BEHOV]) {
sikkerLogger.info("Id $jobbId finnes fra før med annet behov. Lagrer en ny jobb.")
val uliktBehov =
Key.BEHOV in utloesendeMelding &&
utloesendeMelding[Key.BEHOV] != eksisterendeJobb.data.parseJson().toMap()[Key.BEHOV]
val ulikEvent =
Key.EVENT_NAME in utloesendeMelding &&
utloesendeMelding[Key.EVENT_NAME] != eksisterendeJobb.data.parseJson().toMap()[Key.EVENT_NAME]

if (uliktBehov || ulikEvent) {
sikkerLogger.info("ID $jobbId finnes fra før med annet behov/event. Lagrer en ny jobb.")
val nyTransaksjonId = UUID.randomUUID()
val utloesendeMeldingMedNyTransaksjonId = fail.utloesendeMelding.toMap() + mapOf(Key.UUID to nyTransaksjonId.toJson(UuidSerializer))
val utloesendeMeldingMedNyTransaksjonId = utloesendeMelding.plus(Key.UUID to nyTransaksjonId.toJson())
lagre(
Bakgrunnsjobb(nyTransaksjonId, type = jobbType, data = utloesendeMeldingMedNyTransaksjonId.toJson().toString(), maksAntallForsoek = 10),
Bakgrunnsjobb(
uuid = nyTransaksjonId,
type = jobbType,
data = utloesendeMeldingMedNyTransaksjonId.toJson().toString(),
maksAntallForsoek = 10,
),
)
} else {
oppdater(eksisterendeJobb)
Expand All @@ -102,7 +115,7 @@ class FeilLytter(
// BakgrunnsjobbService finnVentende() tar heller ikke hensyn til forsøk, kun status på jobben!
if (jobb.forsoek > jobb.maksAntallForsoek) {
jobb.status = BakgrunnsjobbStatus.STOPPET
sikkerLogger.warn("Maks forsøk nådd, stopper jobb med id ${jobb.uuid} permanent!")
sikkerLogger.error("Maks forsøk nådd, stopper jobb med id ${jobb.uuid} permanent!")
} else {
jobb.status = BakgrunnsjobbStatus.FEILET
}
Expand All @@ -123,17 +136,23 @@ class FeilLytter(
}
}

fun behovSkalHaandteres(fail: Fail): Boolean {
val behovFraMelding = fail.utloesendeMelding.toMap()[Key.BEHOV]?.fromJson(BehovType.serializer())
fun behovSkalHaandteres(utloesendeMelding: Map<Key, JsonElement>): Boolean {
val behovFraMelding = utloesendeMelding[Key.BEHOV]?.fromJson(BehovType.serializer())
val skalHaandteres = behovSomHaandteres.contains(behovFraMelding)
sikkerLogger.info("Behov: $behovFraMelding skal håndteres: $skalHaandteres")
return skalHaandteres
}

fun eventSkalHaandteres(fail: Fail): Boolean {
val eventFraMelding = fail.utloesendeMelding.toMap()[Key.EVENT_NAME]?.fromJson(EventName.serializer())
fun eventSkalHaandteres(utloesendeMelding: Map<Key, JsonElement>): Boolean {
val eventFraMelding = utloesendeMelding[Key.EVENT_NAME]?.fromJson(EventName.serializer())
val skalHaandteres = eventerSomHaandteres.contains(eventFraMelding)
sikkerLogger.info("Event: $eventFraMelding skal håndteres: $skalHaandteres")
return skalHaandteres
}
}

fun JsonElement.toFailOrNull(): Fail? =
toMap()[Key.FAIL]
?.runCatching {
fromJson(Fail.serializer())
}?.getOrNull()
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package no.nav.helsearbeidsgiver.inntektsmelding.feilbehandler.river

import com.github.navikt.tbd_libs.rapids_and_rivers.JsonMessage
import com.github.navikt.tbd_libs.rapids_and_rivers.test_support.TestRapid
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.booleans.shouldBeTrue
import io.kotest.matchers.equals.shouldNotBeEqual
import io.kotest.matchers.ints.shouldBeExactly
import io.kotest.matchers.maps.shouldContainExactly
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import no.nav.hag.utils.bakgrunnsjobb.Bakgrunnsjobb
import no.nav.hag.utils.bakgrunnsjobb.BakgrunnsjobbStatus
import no.nav.hag.utils.bakgrunnsjobb.MockBakgrunnsjobbRepository
Expand All @@ -16,8 +20,9 @@ import no.nav.helsearbeidsgiver.felles.json.les
import no.nav.helsearbeidsgiver.felles.json.toJson
import no.nav.helsearbeidsgiver.felles.json.toMap
import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail
import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.ModelUtils.toFailOrNull
import no.nav.helsearbeidsgiver.felles.test.rapidsrivers.sendJson
import no.nav.helsearbeidsgiver.inntektsmelding.feilbehandler.prosessor.FeilProsessor
import no.nav.helsearbeidsgiver.utils.json.fromJson
import no.nav.helsearbeidsgiver.utils.json.parseJson
import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer
import no.nav.helsearbeidsgiver.utils.json.toJson
Expand All @@ -37,34 +42,39 @@ class FeilLytterTest :
}

test("skal håndtere gyldige feil med spesifiserte behov") {
handler.behovSomHaandteres.forEach { handler.behovSkalHaandteres(lagGyldigFeil(it)) shouldBe true }
handler.behovSomHaandteres.forEach { handler.behovSkalHaandteres(utloesendeMelding(it)) shouldBe true }
}

test("skal ignorere gyldige feil med visse behov") {
val ignorerteBehov = BehovType.entries.filterNot { handler.behovSomHaandteres.contains(it) }
ignorerteBehov.forEach { handler.behovSkalHaandteres(lagGyldigFeil(it)) shouldBe false }
ignorerteBehov.forEach { handler.behovSkalHaandteres(utloesendeMelding(it)) shouldBe false }
}

test("skal ignorere feil uten behov") {
val uuid = UUID.randomUUID()
val feil =
lagGyldigFeil(BehovType.LAGRE_JOURNALPOST_ID).copy(
utloesendeMelding =
JsonMessage
.newMessage(
mapOf(
Key.UUID.str to uuid,
Key.FORESPOERSEL_ID.str to uuid,
),
).toJson()
.parseJson(),
val utloesendeMelding =
mapOf(
Key.UUID to UUID.randomUUID().toJson(),
Key.FORESPOERSEL_ID to UUID.randomUUID().toJson(),
)
handler.behovSkalHaandteres(feil) shouldBe false
handler.behovSkalHaandteres(utloesendeMelding) shouldBe false
}

test("skal behandle feil uten behov, men med spesifiserte eventer") {
handler.eventerSomHaandteres.forEach { event ->
val utloesendeMelding =
mapOf(
Key.EVENT_NAME to event.toJson(),
Key.UUID to UUID.randomUUID().toJson(),
Key.FORESPOERSEL_ID to UUID.randomUUID().toJson(),
)

handler.eventSkalHaandteres(utloesendeMelding).shouldBeTrue()
}
}

test("skal håndtere feil uten forespørselId") {
val feil = lagGyldigFeilUtenForespoerselId(BehovType.LAGRE_JOURNALPOST_ID)
handler.behovSkalHaandteres(feil) shouldBe true
val utloesendeMelding = utloesendeMelding(BehovType.LAGRE_JOURNALPOST_ID).minus(Key.FORESPOERSEL_ID)
handler.behovSkalHaandteres(utloesendeMelding) shouldBe true
}

test("Ny feil med forskjellig behov og samme id skal lagres") {
Expand Down Expand Up @@ -97,7 +107,7 @@ class FeilLytterTest :
test("Skal sette jobb til STOPPET når maks antall forsøk er overskredet") {
val now = LocalDateTime.now()
val feilmelding = lagRapidFeilmelding()
val feil = toFailOrNull(feilmelding.parseJson().toMap())!!
val feil = feilmelding.parseJson().toFailOrNull()!!

repository.save(
Bakgrunnsjobb(
Expand Down Expand Up @@ -136,6 +146,102 @@ class FeilLytterTest :
repository.findByKjoeretidBeforeAndStatusIn(now.plusMinutes(1), setOf(BakgrunnsjobbStatus.OPPRETTET), true).size shouldBe 1
repository.findByKjoeretidBeforeAndStatusIn(now.plusMinutes(1), setOf(BakgrunnsjobbStatus.FEILET), true).size shouldBe 1
}

test("ved flere feil på samme transaksjon-ID og event, så oppdateres eksisterende jobb") {
val omEttMinutt = LocalDateTime.now().plusMinutes(1)
val forespoerselMottattFail = lagFail(EventName.FORESPOERSEL_MOTTATT)

rapid.sendJson(forespoerselMottattFail.tilMelding())

repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.FEILET), true).size shouldBeExactly 0
repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.OPPRETTET), true).size shouldBeExactly 1

rapid.sendJson(forespoerselMottattFail.tilMelding())

val jobber = repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.FEILET), true)
repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.OPPRETTET), true).size shouldBeExactly 0

jobber.size shouldBeExactly 1

jobber[0].uuid shouldBe forespoerselMottattFail.transaksjonId
jobber[0].data.parseJson().toMap() shouldContainExactly forespoerselMottattFail.utloesendeMelding.toMap()
}

test("ved flere feil på samme transaksjon-ID, men ulik event, så lagres to jobber med ulik transaksjon-ID") {
val omEttMinutt = LocalDateTime.now().plusMinutes(1)
val transaksjonId = UUID.randomUUID()
val forespoerselMottattFail = lagFail(EventName.FORESPOERSEL_MOTTATT, transaksjonId)
val forespoerselBesvartFail = lagFail(EventName.FORESPOERSEL_BESVART, transaksjonId)

rapid.sendJson(forespoerselMottattFail.tilMelding())

repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.FEILET), true).size shouldBeExactly 0
repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.OPPRETTET), true).size shouldBeExactly 1

rapid.sendJson(forespoerselBesvartFail.tilMelding())

repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.FEILET), true).size shouldBeExactly 0
val jobber = repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.OPPRETTET), true)

jobber.size shouldBeExactly 2

jobber[0].uuid shouldBe transaksjonId
jobber[0].data.parseJson().toMap() shouldContainExactly forespoerselMottattFail.utloesendeMelding.toMap()

jobber[1].uuid shouldNotBe transaksjonId
jobber[1].data.parseJson().toMap().also {
it[Key.EVENT_NAME]?.fromJson(EventName.serializer()) shouldBe forespoerselBesvartFail.event
it[Key.UUID]?.fromJson(UuidSerializer) shouldNotBe transaksjonId
}
}

test("ved flere feil på ulik transaksjon-ID, men samme event, så lagres to jobber (med ulik transaksjon-ID)") {
val omEttMinutt = LocalDateTime.now().plusMinutes(1)
val forespoerselMottattFail1 = lagFail(EventName.FORESPOERSEL_MOTTATT)
val forespoerselMottattFail2 = lagFail(EventName.FORESPOERSEL_MOTTATT)

rapid.sendJson(forespoerselMottattFail1.tilMelding())

repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.FEILET), true).size shouldBeExactly 0
repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.OPPRETTET), true).size shouldBeExactly 1

rapid.sendJson(forespoerselMottattFail2.tilMelding())

repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.FEILET), true).size shouldBeExactly 0
val jobber = repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.OPPRETTET), true)

jobber.size shouldBeExactly 2

jobber[0].uuid shouldBe forespoerselMottattFail1.transaksjonId
jobber[0].data.parseJson().toMap() shouldContainExactly forespoerselMottattFail1.utloesendeMelding.toMap()

jobber[1].uuid shouldBe forespoerselMottattFail2.transaksjonId
jobber[1].data.parseJson().toMap() shouldContainExactly forespoerselMottattFail2.utloesendeMelding.toMap()
}

test("ved flere feil på ulik transaksjon-ID og ulik event, så lagres to jobber (med ulik transaksjon-ID)") {
val omEttMinutt = LocalDateTime.now().plusMinutes(1)
val forespoerselMottattFail = lagFail(EventName.FORESPOERSEL_MOTTATT)
val forespoerselBesvartFail = lagFail(EventName.FORESPOERSEL_BESVART)

rapid.sendJson(forespoerselMottattFail.tilMelding())

repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.FEILET), true).size shouldBeExactly 0
repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.OPPRETTET), true).size shouldBeExactly 1

rapid.sendJson(forespoerselBesvartFail.tilMelding())

repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.FEILET), true).size shouldBeExactly 0
val jobber = repository.findByKjoeretidBeforeAndStatusIn(omEttMinutt, setOf(BakgrunnsjobbStatus.OPPRETTET), true)

jobber.size shouldBeExactly 2

jobber[0].uuid shouldBe forespoerselMottattFail.transaksjonId
jobber[0].data.parseJson().toMap() shouldContainExactly forespoerselMottattFail.utloesendeMelding.toMap()

jobber[1].uuid shouldBe forespoerselBesvartFail.transaksjonId
jobber[1].data.parseJson().toMap() shouldContainExactly forespoerselBesvartFail.utloesendeMelding.toMap()
}
})

fun lagRapidFeilmelding(
Expand Down Expand Up @@ -164,30 +270,26 @@ fun lagRapidFeilmelding(
.toString()
}

fun lagGyldigFeil(behov: BehovType): Fail {
val transaksjonId = UUID.randomUUID()
val forespoerselID = UUID.randomUUID()
val jsonMessage =
JsonMessage.newMessage(
EventName.KVITTERING_REQUESTED.name,
fun lagFail(
eventName: EventName,
transaksjonId: UUID = UUID.randomUUID(),
): Fail =
Fail(
feilmelding = "skux life",
event = eventName,
transaksjonId = transaksjonId,
forespoerselId = null,
utloesendeMelding =
mapOf(
Key.BEHOV.str to behov,
Key.UUID.str to transaksjonId,
Key.FORESPOERSEL_ID.str to forespoerselID,
),
)
return Fail("Feil", EventName.KVITTERING_REQUESTED, transaksjonId, forespoerselID, jsonMessage.toJson().parseJson())
}
Key.EVENT_NAME to eventName.toJson(),
Key.UUID to transaksjonId.toJson(),
).toJson(),
)

fun lagGyldigFeilUtenForespoerselId(behov: BehovType): Fail {
val transaksjonId = UUID.randomUUID()
val jsonMessage =
JsonMessage.newMessage(
EventName.KVITTERING_REQUESTED.name,
mapOf(
Key.BEHOV.str to behov,
Key.UUID.str to transaksjonId,
),
)
return Fail("Feil", EventName.KVITTERING_REQUESTED, transaksjonId, null, jsonMessage.toJson().parseJson())
}
fun utloesendeMelding(behov: BehovType): Map<Key, JsonElement> =
mapOf(
Key.EVENT_NAME to EventName.KVITTERING_REQUESTED.toJson(),
Key.BEHOV to behov.toJson(),
Key.UUID to UUID.randomUUID().toJson(),
Key.FORESPOERSEL_ID to UUID.randomUUID().toJson(),
)
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum class Key(
ORG_RETTIGHETER("org_rettigheter"),
FORESPOERSEL_SVAR("forespoersel-svar"),
FORESPOERSEL_MAP("forespoersel_map"),
FORESPOERSEL("forespoersel"),
INNTEKT("inntekt"),
FNR("fnr"),
FNR_LISTE("fnr_liste"),
Expand Down
Loading

0 comments on commit 0761ae2

Please sign in to comment.