From bd0c98d35364bbe235467aae3ab32aab2d064db0 Mon Sep 17 00:00:00 2001 From: Mikael Bjerga <6940327+bjerga@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:52:12 +0100 Subject: [PATCH] =?UTF-8?q?Lagre=20=C3=A5pen=20inntektsmelding=20(#403)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Lagre åpen inntektsmelding * Fjern unødvendige exceptions * Rett navnefeil i metric * Slett ubrukt testkode --- .../aapenimservice/AapenImService.kt | 61 +++++----- .../inntektsmelding/altinn/AltinnLoeser.kt | 2 +- .../inntektsmelding/db/AapenImRepo.kt | 62 ++++++++++ .../inntektsmelding/db/App.kt | 51 +++++---- .../db/ForespoerselRepository.kt | 8 +- .../db/InntektsmeldingRepository.kt | 30 ++--- .../inntektsmelding/db/config/Database.kt | 41 +++++-- .../db/config/DatabaseConfig.kt | 24 ---- .../inntektsmelding/db/config/DbUtils.kt | 7 ++ .../db/river/HentAapenImRiver.kt | 108 ++++++++++++++++++ .../db/river/LagreAapenImRiver.kt | 99 ++++++++++++++++ .../db/tabell/AapenInntektsmeldingEntitet.kt | 21 ++++ .../{config => tabell}/ForespoerselEntitet.kt | 2 +- .../InntektsmeldingEntitet.kt | 2 +- .../migration/V11__aapen_inntektsmelding.sql | 10 ++ .../inntektsmelding/db/LocalApp.kt | 12 -- .../inntektsmelding/db/RepositoryTest.kt | 39 +++---- .../helsearbeidsgiver/felles/EventTypes.kt | 7 ++ .../felles/loeser/ObjectRiver.kt | 24 ++-- .../felles/metrics/Metrics.kt | 21 +++- .../inntektsmelding/integrasjonstest/App.kt | 51 +-------- .../src/main/resources/logback.xml | 16 --- .../integrasjonstest/utils/EndToEndTest.kt | 8 +- .../trengerservice/TrengerService.kt | 4 +- 24 files changed, 484 insertions(+), 226 deletions(-) create mode 100644 db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/AapenImRepo.kt delete mode 100644 db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/DatabaseConfig.kt create mode 100644 db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/DbUtils.kt create mode 100644 db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentAapenImRiver.kt create mode 100644 db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/LagreAapenImRiver.kt create mode 100644 db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/tabell/AapenInntektsmeldingEntitet.kt rename db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/{config => tabell}/ForespoerselEntitet.kt (87%) rename db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/{config => tabell}/InntektsmeldingEntitet.kt (95%) create mode 100644 db/src/main/resources/db/migration/V11__aapen_inntektsmelding.sql delete mode 100644 db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/LocalApp.kt delete mode 100644 integrasjonstest/src/main/resources/logback.xml diff --git a/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/AapenImService.kt b/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/AapenImService.kt index a2b4054b3e..616a1e8cc3 100644 --- a/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/AapenImService.kt +++ b/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/AapenImService.kt @@ -26,7 +26,6 @@ import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore import no.nav.helsearbeidsgiver.felles.utils.Log import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer import no.nav.helsearbeidsgiver.utils.json.toJson -import no.nav.helsearbeidsgiver.utils.json.toJsonStr import no.nav.helsearbeidsgiver.utils.json.toPretty import no.nav.helsearbeidsgiver.utils.log.MdcUtils import no.nav.helsearbeidsgiver.utils.log.logger @@ -53,8 +52,7 @@ class AapenImService( Key.VIRKSOMHET, Key.ARBEIDSTAKER_INFORMASJON, Key.ARBEIDSGIVER_INFORMASJON, - Key.AAPEN_INNTEKTMELDING, - Key.ER_DUPLIKAT_IM + Key.AAPEN_INNTEKTMELDING ) private val step1Data = @@ -111,7 +109,7 @@ class AapenImService( Log.transaksjonId(transaksjonId), Log.aapenId(aapenId) ) { - if (step1Data.all { it in melding }) { + if (step1Data.all(melding::containsKey)) { val skjema = Key.SKJEMA_INNTEKTSMELDING.les(SkjemaInntektsmelding.serializer(), melding) val orgNavn = Key.VIRKSOMHET.les(String.serializer(), melding) val sykmeldt = Key.ARBEIDSTAKER_INFORMASJON.les(PersonDato.serializer(), melding) @@ -125,19 +123,17 @@ class AapenImService( avsender = avsender ) - logger.debug("Skal sende melding med behov 'BehovType.LAGRE_AAPEN_IM'") - sikkerLogger.debug("Skal sende melding med behov 'BehovType.LAGRE_AAPEN_IM'") -// rapid.publish( -// Key.EVENT_NAME to event.toJson(), -// Key.UUID to transaksjonId.toJson(), -// Key.AAPEN_ID to aapenId.toJson(), -// Key.BEHOV to BehovType.LAGRE_AAPEN_IM.toJson(), -// Key.AAPEN_INNTEKTMELDING to inntektsmelding.toJson(Inntektsmelding.serializer()) -// ) - - // TODO Midlertidig sett svar til im-api - val clientId = redisStore.get(RedisKey.of(transaksjonId, event))!!.let(UUID::fromString) - redisStore.set(RedisKey.of(clientId), inntektsmelding.toJsonStr(Inntektsmelding.serializer())) + rapid.publish( + Key.EVENT_NAME to event.toJson(), + Key.BEHOV to BehovType.LAGRE_AAPEN_IM.toJson(), + Key.UUID to transaksjonId.toJson(), + Key.AAPEN_ID to aapenId.toJson(), + Key.AAPEN_INNTEKTMELDING to inntektsmelding.toJson(Inntektsmelding.serializer()) + ) + .also { + logger.info("Publiserte melding med behov '${BehovType.LAGRE_AAPEN_IM}'.") + sikkerLogger.info("Publiserte melding:\n${it.toPretty()}") + } } } } @@ -145,7 +141,6 @@ class AapenImService( override fun finalize(melding: Map) { val transaksjonId = Key.UUID.les(UuidSerializer, melding) val aapenId = Key.AAPEN_ID.les(UuidSerializer, melding) - val erDuplikat = Key.ER_DUPLIKAT_IM.les(Boolean.serializer(), melding) val inntektsmeldingJson = Key.AAPEN_INNTEKTMELDING.les(JsonElement.serializer(), melding) MdcUtils.withLogFields( @@ -162,22 +157,20 @@ class AapenImService( redisStore.set(RedisKey.of(clientId), inntektsmeldingJson.toString()) } - if (!erDuplikat) { - rapid.publish( - Key.EVENT_NAME to EventName.AAPEN_IM_LAGRET.toJson(), - Key.UUID to transaksjonId.toJson(), - Key.AAPEN_ID to aapenId.toJson(), - Key.AAPEN_INNTEKTMELDING to inntektsmeldingJson - ) - .also { - MdcUtils.withLogFields( - Log.event(EventName.AAPEN_IM_LAGRET) - ) { - logger.info("Publiserte melding.") - sikkerLogger.info("Publiserte melding:\n${it.toPretty()}") - } + rapid.publish( + Key.EVENT_NAME to EventName.AAPEN_IM_LAGRET.toJson(), + Key.UUID to transaksjonId.toJson(), + Key.AAPEN_ID to aapenId.toJson(), + Key.AAPEN_INNTEKTMELDING to inntektsmeldingJson + ) + .also { + MdcUtils.withLogFields( + Log.event(EventName.AAPEN_IM_LAGRET) + ) { + logger.info("Publiserte melding.") + sikkerLogger.info("Publiserte melding:\n${it.toPretty()}") } - } + } } } @@ -194,6 +187,7 @@ class AapenImService( Key.VIRKSOMHET to "Ukjent virksomhet".toJson() ) } + BehovType.FULLT_NAVN -> { val sykmeldtFnr = Key.IDENTITETSNUMMER.les(String.serializer(), melding) val avsenderFnr = Key.ARBEIDSGIVER_ID.les(String.serializer(), melding) @@ -202,6 +196,7 @@ class AapenImService( Key.ARBEIDSGIVER_INFORMASJON to tomPerson(avsenderFnr).toJson(PersonDato.serializer()) ) } + else -> { emptyList() } diff --git a/altinn/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/altinn/AltinnLoeser.kt b/altinn/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/altinn/AltinnLoeser.kt index 5c2c509b4d..0311fc2c93 100644 --- a/altinn/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/altinn/AltinnLoeser.kt +++ b/altinn/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/altinn/AltinnLoeser.kt @@ -36,7 +36,7 @@ class AltinnLoeser( identitetsnummer = Key.IDENTITETSNUMMER.les(String.serializer(), json) ) - override fun Melding.haandter(): Map { + override fun Melding.haandter(json: Map): Map { val rettigheterForenklet = Metrics.altinnRequest.recordTime { altinnClient diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/AapenImRepo.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/AapenImRepo.kt new file mode 100644 index 0000000000..6b36bc8f5a --- /dev/null +++ b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/AapenImRepo.kt @@ -0,0 +1,62 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.db + +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Inntektsmelding +import no.nav.helsearbeidsgiver.felles.metrics.Metrics +import no.nav.helsearbeidsgiver.felles.metrics.recordTime +import no.nav.helsearbeidsgiver.inntektsmelding.db.config.firstOrNull +import no.nav.helsearbeidsgiver.inntektsmelding.db.tabell.AapenInntektsmeldingEntitet +import org.jetbrains.exposed.sql.Database +import org.jetbrains.exposed.sql.Query +import org.jetbrains.exposed.sql.SortOrder +import org.jetbrains.exposed.sql.and +import org.jetbrains.exposed.sql.insert +import org.jetbrains.exposed.sql.select +import org.jetbrains.exposed.sql.transactions.transaction +import org.jetbrains.exposed.sql.update +import java.util.UUID + +// TODO test +class AapenImRepo(private val db: Database) { + + fun hentNyesteIm(aapenId: UUID): Inntektsmelding? = + Metrics.dbAapenIm.recordTime(::hentNyesteIm.name) { + transaction(db) { + hentNyesteImQuery(aapenId) + .firstOrNull(AapenInntektsmeldingEntitet.inntektsmelding) + } + } + + fun lagreIm(aapenId: UUID, im: Inntektsmelding) { + Metrics.dbAapenIm.recordTime(::lagreIm.name) { + transaction(db) { + AapenInntektsmeldingEntitet.insert { + it[this.aapenId] = aapenId + it[inntektsmelding] = im + } + } + } + } + + fun oppdaterJournalpostId(aapenId: UUID, journalpostId: String) { + Metrics.dbAapenIm.recordTime(::oppdaterJournalpostId.name) { + transaction(db) { + AapenInntektsmeldingEntitet.update( + where = { + (AapenInntektsmeldingEntitet.id eqSubQuery hentNyesteImQuery(aapenId).adjustSlice { slice(AapenInntektsmeldingEntitet.id) }) and + AapenInntektsmeldingEntitet.journalpostId.isNull() + } + ) { + it[this.journalpostId] = journalpostId + } + } + } + } +} + +private fun hentNyesteImQuery(aapenId: UUID): Query = + AapenInntektsmeldingEntitet + .select { + AapenInntektsmeldingEntitet.aapenId eq aapenId + } + .orderBy(AapenInntektsmeldingEntitet.opprettet, SortOrder.DESC) + .limit(1) diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/App.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/App.kt index 6fa1d7f8db..baaa0f86c6 100644 --- a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/App.kt +++ b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/App.kt @@ -1,13 +1,12 @@ package no.nav.helsearbeidsgiver.inntektsmelding.db -import com.zaxxer.hikari.HikariConfig import no.nav.helse.rapids_rivers.RapidApplication import no.nav.helse.rapids_rivers.RapidsConnection import no.nav.helsearbeidsgiver.inntektsmelding.db.config.Database -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.DatabaseConfig -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.mapHikariConfig +import no.nav.helsearbeidsgiver.inntektsmelding.db.river.HentAapenImRiver import no.nav.helsearbeidsgiver.inntektsmelding.db.river.HentOrgnrLoeser import no.nav.helsearbeidsgiver.inntektsmelding.db.river.HentPersistertLoeser +import no.nav.helsearbeidsgiver.inntektsmelding.db.river.LagreAapenImRiver import no.nav.helsearbeidsgiver.inntektsmelding.db.river.LagreEksternInntektsmeldingLoeser import no.nav.helsearbeidsgiver.inntektsmelding.db.river.LagreForespoerselLoeser import no.nav.helsearbeidsgiver.inntektsmelding.db.river.LagreJournalpostIdLoeser @@ -16,29 +15,32 @@ import no.nav.helsearbeidsgiver.inntektsmelding.db.river.PersisterImLoeser import no.nav.helsearbeidsgiver.inntektsmelding.db.river.PersisterOppgaveLoeser import no.nav.helsearbeidsgiver.inntektsmelding.db.river.PersisterSakLoeser import no.nav.helsearbeidsgiver.utils.log.logger -import no.nav.helsearbeidsgiver.utils.log.sikkerLogger private val logger = "helsearbeidsgiver-im-db".logger() -private val sikkerLogger = sikkerLogger() fun main() { - buildApp(mapHikariConfig(DatabaseConfig()), System.getenv()).start() -} + val database = Database(Database.Secrets("NAIS_DATABASE_IM_DB_INNTEKTSMELDING")) -fun buildApp(config: HikariConfig, env: Map): RapidsConnection { - val database = Database(config) - sikkerLogger.info("Bruker database url: ${config.jdbcUrl}") logger.info("Migrering starter...") database.migrate() logger.info("Migrering ferdig.") + val imRepo = InntektsmeldingRepository(database.db) + val aapenImRepo = AapenImRepo(database.db) val forespoerselRepo = ForespoerselRepository(database.db) + return RapidApplication - .create(env) - .createDb(database, imRepo, forespoerselRepo) + .create(System.getenv()) + .createDbRivers(imRepo, aapenImRepo, forespoerselRepo) + .registerDbLifecycle(database) + .start() } -fun RapidsConnection.createDb(database: Database, imRepo: InntektsmeldingRepository, forespoerselRepo: ForespoerselRepository): RapidsConnection = +fun RapidsConnection.createDbRivers( + imRepo: InntektsmeldingRepository, + aapenImRepo: AapenImRepo, + forespoerselRepo: ForespoerselRepository +): RapidsConnection = also { logger.info("Starter ${LagreForespoerselLoeser::class.simpleName}...") LagreForespoerselLoeser(this, forespoerselRepo) @@ -67,14 +69,19 @@ fun RapidsConnection.createDb(database: Database, imRepo: InntektsmeldingReposit logger.info("Starter ${LagreEksternInntektsmeldingLoeser::class.simpleName}...") LagreEksternInntektsmeldingLoeser(this, imRepo) - registerDbLifecycle(database) + logger.info("Starter ${HentAapenImRiver::class.simpleName}...") + HentAapenImRiver(aapenImRepo).connect(this) + + logger.info("Starter ${LagreAapenImRiver::class.simpleName}...") + LagreAapenImRiver(aapenImRepo).connect(this) } -private fun RapidsConnection.registerDbLifecycle(db: Database) { - register(object : RapidsConnection.StatusListener { - override fun onShutdown(rapidsConnection: RapidsConnection) { - logger.info("Mottatt stoppsignal, lukker databasetilkobling") - db.dataSource.close() - } - }) -} +fun RapidsConnection.registerDbLifecycle(db: Database): RapidsConnection = + also { + it.register(object : RapidsConnection.StatusListener { + override fun onShutdown(rapidsConnection: RapidsConnection) { + logger.info("Stoppsignal mottatt, lukker databasetilkobling.") + db.dataSource.close() + } + }) + } diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/ForespoerselRepository.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/ForespoerselRepository.kt index 6cacb76571..1e15b41d38 100644 --- a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/ForespoerselRepository.kt +++ b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/ForespoerselRepository.kt @@ -1,10 +1,9 @@ package no.nav.helsearbeidsgiver.inntektsmelding.db import io.prometheus.client.Summary -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.ForespoerselEntitet +import no.nav.helsearbeidsgiver.inntektsmelding.db.config.firstOrNull +import no.nav.helsearbeidsgiver.inntektsmelding.db.tabell.ForespoerselEntitet import org.jetbrains.exposed.sql.Database -import org.jetbrains.exposed.sql.Expression -import org.jetbrains.exposed.sql.Query import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.insert import org.jetbrains.exposed.sql.select @@ -94,6 +93,3 @@ class ForespoerselRepository(private val db: Database) { } } } - -private fun Query.firstOrNull(c: Expression): T? = - firstOrNull()?.getOrNull(c) diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/InntektsmeldingRepository.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/InntektsmeldingRepository.kt index e0787e9b0c..528c00990d 100644 --- a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/InntektsmeldingRepository.kt +++ b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/InntektsmeldingRepository.kt @@ -3,9 +3,7 @@ package no.nav.helsearbeidsgiver.inntektsmelding.db import io.prometheus.client.Summary import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.Inntektsmelding import no.nav.helsearbeidsgiver.felles.EksternInntektsmelding -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.InntektsmeldingEntitet -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.InntektsmeldingEntitet.forespoerselId -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.InntektsmeldingEntitet.innsendt +import no.nav.helsearbeidsgiver.inntektsmelding.db.tabell.InntektsmeldingEntitet import no.nav.helsearbeidsgiver.utils.log.logger import no.nav.helsearbeidsgiver.utils.log.sikkerLogger import org.jetbrains.exposed.sql.Database @@ -59,16 +57,20 @@ class InntektsmeldingRepository(private val db: Database) { fun hentNyesteEksternEllerInternInntektsmelding(forespørselId: String): Pair? { val requestTimer = requestLatency.labels("hentNyesteInternEllerEkstern").startTimer() return transaction(db) { - InntektsmeldingEntitet.slice(InntektsmeldingEntitet.dokument, InntektsmeldingEntitet.eksternInntektsmelding).run { - select { (forespoerselId eq forespørselId) }.orderBy(innsendt, SortOrder.DESC) - }.limit(1).map { - Pair( - it[InntektsmeldingEntitet.dokument], - it[InntektsmeldingEntitet.eksternInntektsmelding] - ) - }.firstOrNull().also { - requestTimer.observeDuration() - } + InntektsmeldingEntitet.slice(InntektsmeldingEntitet.dokument, InntektsmeldingEntitet.eksternInntektsmelding) + .select { (InntektsmeldingEntitet.forespoerselId eq forespørselId) } + .orderBy(InntektsmeldingEntitet.innsendt, SortOrder.DESC) + .limit(1) + .map { + Pair( + it[InntektsmeldingEntitet.dokument], + it[InntektsmeldingEntitet.eksternInntektsmelding] + ) + } + .firstOrNull() + .also { + requestTimer.observeDuration() + } } } @@ -110,6 +112,6 @@ class InntektsmeldingRepository(private val db: Database) { InntektsmeldingEntitet.select { (InntektsmeldingEntitet.forespoerselId eq forespoerselId.toString()) and InntektsmeldingEntitet.dokument.isNotNull() } - .orderBy(innsendt, SortOrder.DESC) + .orderBy(InntektsmeldingEntitet.innsendt, SortOrder.DESC) .limit(1) } diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/Database.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/Database.kt index aef4bb11dd..fd14559b46 100644 --- a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/Database.kt +++ b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/Database.kt @@ -2,15 +2,20 @@ package no.nav.helsearbeidsgiver.inntektsmelding.db.config import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariDataSource +import no.nav.helsearbeidsgiver.felles.fromEnv import org.flywaydb.core.Flyway import org.jetbrains.exposed.sql.Database as ExposedDatabase class Database( - dbConfig: HikariConfig + private val config: HikariConfig ) { - val dataSource by lazy { HikariDataSource(dbConfig) } + constructor(secrets: Secrets) : this( + dbConfig(secrets) + ) + + val dataSource by lazy { HikariDataSource(config) } val db by lazy { ExposedDatabase.connect(dataSource) } - private val config = dbConfig + fun migrate() { migrationConfig(config) .let(::HikariDataSource) @@ -20,14 +25,34 @@ class Database( .lockRetryCount(50) .load() .migrate() - }.close() + } + .close() + } + + class Secrets(prefix: String) { + val username = "${prefix}_USERNAME".fromEnv() + val password = "${prefix}_PASSWORD".fromEnv() + + val url = "jdbc:postgresql://%s:%s/%s".format( + "${prefix}_HOST".fromEnv(), + "${prefix}_PORT".fromEnv(), + "${prefix}_DATABASE".fromEnv() + ) } } -private fun migrationConfig(conf: HikariConfig): HikariConfig = +private fun dbConfig(secrets: Database.Secrets): HikariConfig = + HikariConfig().apply { + jdbcUrl = secrets.url + username = secrets.username + password = secrets.password + maximumPoolSize = 5 + } + +private fun migrationConfig(config: HikariConfig): HikariConfig = HikariConfig().apply { - jdbcUrl = conf.jdbcUrl - username = conf.username - password = conf.password + jdbcUrl = config.jdbcUrl + username = config.username + password = config.password maximumPoolSize = 3 } diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/DatabaseConfig.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/DatabaseConfig.kt deleted file mode 100644 index 13b8aa8a39..0000000000 --- a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/DatabaseConfig.kt +++ /dev/null @@ -1,24 +0,0 @@ -package no.nav.helsearbeidsgiver.inntektsmelding.db.config - -import com.zaxxer.hikari.HikariConfig -import no.nav.helsearbeidsgiver.felles.fromEnv - -private const val prefix = "NAIS_DATABASE_IM_DB_INNTEKTSMELDING" - -data class DatabaseConfig( - val host: String = "${prefix}_HOST".fromEnv(), - val port: String = "${prefix}_PORT".fromEnv(), - val name: String = "${prefix}_DATABASE".fromEnv(), - val username: String = "${prefix}_USERNAME".fromEnv(), - val password: String = "${prefix}_PASSWORD".fromEnv(), - val url: String = "jdbc:postgresql://%s:%s/%s".format(host, port, name) -) - -fun mapHikariConfig(databaseConfig: DatabaseConfig): HikariConfig { - return HikariConfig().apply { - jdbcUrl = databaseConfig.url - username = databaseConfig.username - password = databaseConfig.password - maximumPoolSize = 5 - } -} diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/DbUtils.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/DbUtils.kt new file mode 100644 index 0000000000..cd0eb90c7c --- /dev/null +++ b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/DbUtils.kt @@ -0,0 +1,7 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.db.config + +import org.jetbrains.exposed.sql.Column +import org.jetbrains.exposed.sql.Query + +fun Query.firstOrNull(col: Column): T? = + firstOrNull()?.getOrNull(col) diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentAapenImRiver.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentAapenImRiver.kt new file mode 100644 index 0000000000..16624f353f --- /dev/null +++ b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentAapenImRiver.kt @@ -0,0 +1,108 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.db.river + +import kotlinx.serialization.json.JsonElement +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Inntektsmelding +import no.nav.helsearbeidsgiver.felles.BehovType +import no.nav.helsearbeidsgiver.felles.EventName +import no.nav.helsearbeidsgiver.felles.Key +import no.nav.helsearbeidsgiver.felles.json.krev +import no.nav.helsearbeidsgiver.felles.json.les +import no.nav.helsearbeidsgiver.felles.json.toJson +import no.nav.helsearbeidsgiver.felles.loeser.ObjectRiver +import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail +import no.nav.helsearbeidsgiver.felles.utils.Log +import no.nav.helsearbeidsgiver.inntektsmelding.db.AapenImRepo +import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer +import no.nav.helsearbeidsgiver.utils.json.toJson +import no.nav.helsearbeidsgiver.utils.log.MdcUtils +import no.nav.helsearbeidsgiver.utils.log.logger +import no.nav.helsearbeidsgiver.utils.log.sikkerLogger +import java.util.UUID + +data class HentAapenImMelding( + val eventName: EventName, + val behovType: BehovType, + val transaksjonId: UUID, + val aapenId: UUID +) + +// TODO test +class HentAapenImRiver( + private val aapenImRepo: AapenImRepo +) : ObjectRiver() { + + private val logger = logger() + private val sikkerLogger = sikkerLogger() + + override fun les(json: Map): HentAapenImMelding? = + if (setOf(Key.DATA, Key.FAIL).any(json::containsKey)) { + null + } else { + HentAapenImMelding( + eventName = Key.EVENT_NAME.les(EventName.serializer(), json), + behovType = Key.BEHOV.krev(BehovType.HENT_AAPEN_IM, BehovType.serializer(), json), + transaksjonId = Key.UUID.les(UuidSerializer, json), + aapenId = Key.AAPEN_ID.les(UuidSerializer, json) + ) + } + + override fun HentAapenImMelding.haandter(json: Map): Map = + MdcUtils.withLogFields( + Log.klasse(this), + Log.event(eventName), + Log.behov(behovType), + Log.transaksjonId(transaksjonId), + Log.aapenId(aapenId) + ) { + "Skal hente åpen inntektsmelding.".also { + logger.info(it) + sikkerLogger.info(it) + } + + val inntektsmelding = aapenImRepo.hentNyesteIm(aapenId) + + if (inntektsmelding != null) { + "Hentet åpen inntektsmelding.".also { + logger.info(it) + sikkerLogger.info(it) + } + + mapOf( + Key.EVENT_NAME to eventName.toJson(), + Key.UUID to transaksjonId.toJson(), + Key.AAPEN_ID to aapenId.toJson(), + Key.DATA to "".toJson(), + Key.AAPEN_INNTEKTMELDING to inntektsmelding.toJson(Inntektsmelding.serializer()) + ) + } else { + haandterFeil("Fant ikke åpen inntektsmelding.", json) + } + } + + override fun HentAapenImMelding.haandterFeil(json: Map, error: Throwable): Map = + haandterFeil("Klarte ikke hente åpen inntektsmelding.", json, error) + + private fun HentAapenImMelding.haandterFeil( + feilmelding: String, + json: Map, + error: Throwable? = null + ): Map { + val fail = Fail( + feilmelding = feilmelding, + event = eventName, + transaksjonId = transaksjonId, + forespoerselId = null, + utloesendeMelding = json.toJson() + ) + + logger.error(fail.feilmelding) + sikkerLogger.error(fail.feilmelding, error) + + return mapOf( + Key.FAIL to fail.toJson(Fail.serializer()), + Key.EVENT_NAME to fail.event.toJson(), + Key.UUID to fail.transaksjonId.toJson(), + Key.AAPEN_ID to aapenId.toJson() + ) + } +} diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/LagreAapenImRiver.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/LagreAapenImRiver.kt new file mode 100644 index 0000000000..c3a94e6501 --- /dev/null +++ b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/LagreAapenImRiver.kt @@ -0,0 +1,99 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.db.river + +import kotlinx.serialization.json.JsonElement +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Inntektsmelding +import no.nav.helsearbeidsgiver.felles.BehovType +import no.nav.helsearbeidsgiver.felles.EventName +import no.nav.helsearbeidsgiver.felles.Key +import no.nav.helsearbeidsgiver.felles.json.krev +import no.nav.helsearbeidsgiver.felles.json.les +import no.nav.helsearbeidsgiver.felles.json.toJson +import no.nav.helsearbeidsgiver.felles.loeser.ObjectRiver +import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail +import no.nav.helsearbeidsgiver.felles.utils.Log +import no.nav.helsearbeidsgiver.inntektsmelding.db.AapenImRepo +import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer +import no.nav.helsearbeidsgiver.utils.json.toJson +import no.nav.helsearbeidsgiver.utils.log.MdcUtils +import no.nav.helsearbeidsgiver.utils.log.logger +import no.nav.helsearbeidsgiver.utils.log.sikkerLogger +import java.util.UUID + +data class LagreAapenImMelding( + val eventName: EventName, + val behovType: BehovType, + val transaksjonId: UUID, + val aapenId: UUID, + val aapenInntektsmelding: Inntektsmelding +) + +// TODO test +class LagreAapenImRiver( + private val aapenImRepo: AapenImRepo +) : ObjectRiver() { + + private val logger = logger() + private val sikkerLogger = sikkerLogger() + + override fun les(json: Map): LagreAapenImMelding? = + if (setOf(Key.DATA, Key.FAIL).any(json::containsKey)) { + null + } else { + LagreAapenImMelding( + eventName = Key.EVENT_NAME.les(EventName.serializer(), json), + behovType = Key.BEHOV.krev(BehovType.LAGRE_AAPEN_IM, BehovType.serializer(), json), + transaksjonId = Key.UUID.les(UuidSerializer, json), + aapenId = Key.AAPEN_ID.les(UuidSerializer, json), + aapenInntektsmelding = Key.AAPEN_INNTEKTMELDING.les(Inntektsmelding.serializer(), json) + ) + } + + override fun LagreAapenImMelding.haandter(json: Map): Map = + MdcUtils.withLogFields( + Log.klasse(this), + Log.event(eventName), + Log.behov(behovType), + Log.transaksjonId(transaksjonId), + Log.aapenId(aapenId) + ) { + "Skal lagre åpen inntektsmelding.".also { + logger.info(it) + sikkerLogger.info(it) + } + + aapenImRepo.lagreIm(aapenId, aapenInntektsmelding) + + "Lagret åpen inntektsmelding.".also { + logger.info(it) + sikkerLogger.info(it) + } + + mapOf( + Key.EVENT_NAME to eventName.toJson(), + Key.UUID to transaksjonId.toJson(), + Key.AAPEN_ID to aapenId.toJson(), + Key.DATA to "".toJson(), + Key.AAPEN_INNTEKTMELDING to aapenInntektsmelding.toJson(Inntektsmelding.serializer()) + ) + } + + override fun LagreAapenImMelding.haandterFeil(json: Map, error: Throwable): Map { + val fail = Fail( + feilmelding = "Klarte ikke lagre åpen inntektsmelding.", + event = eventName, + transaksjonId = transaksjonId, + forespoerselId = null, + utloesendeMelding = json.toJson() + ) + + logger.error(fail.feilmelding) + sikkerLogger.error(fail.feilmelding, error) + + return mapOf( + Key.FAIL to fail.toJson(Fail.serializer()), + Key.EVENT_NAME to fail.event.toJson(), + Key.UUID to fail.transaksjonId.toJson(), + Key.AAPEN_ID to aapenId.toJson() + ) + } +} diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/tabell/AapenInntektsmeldingEntitet.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/tabell/AapenInntektsmeldingEntitet.kt new file mode 100644 index 0000000000..81be4452f7 --- /dev/null +++ b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/tabell/AapenInntektsmeldingEntitet.kt @@ -0,0 +1,21 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.db.tabell + +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Inntektsmelding +import no.nav.helsearbeidsgiver.utils.json.jsonConfig +import org.jetbrains.exposed.sql.Table +import org.jetbrains.exposed.sql.javatime.datetime +import org.jetbrains.exposed.sql.json.jsonb + +object AapenInntektsmeldingEntitet : Table("aapen_inntektsmelding") { + val id = integer("id").autoIncrement( + idSeqName = "aapen_inntektsmelding_id_seq" + ) + val aapenId = uuid("aapen_id") + val inntektsmelding = jsonb( + name = "inntektsmelding", + jsonConfig = jsonConfig, + kSerializer = Inntektsmelding.serializer() + ) + val journalpostId = text("journalpost_id").nullable() + val opprettet = datetime("opprettet") +} diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/ForespoerselEntitet.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/tabell/ForespoerselEntitet.kt similarity index 87% rename from db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/ForespoerselEntitet.kt rename to db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/tabell/ForespoerselEntitet.kt index 7828580b1c..f6fba5b21a 100644 --- a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/ForespoerselEntitet.kt +++ b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/tabell/ForespoerselEntitet.kt @@ -1,4 +1,4 @@ -package no.nav.helsearbeidsgiver.inntektsmelding.db.config +package no.nav.helsearbeidsgiver.inntektsmelding.db.tabell import org.jetbrains.exposed.sql.Table import org.jetbrains.exposed.sql.javatime.datetime diff --git a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/InntektsmeldingEntitet.kt b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/tabell/InntektsmeldingEntitet.kt similarity index 95% rename from db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/InntektsmeldingEntitet.kt rename to db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/tabell/InntektsmeldingEntitet.kt index 5dc9d08eee..677142a1a2 100644 --- a/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/config/InntektsmeldingEntitet.kt +++ b/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/tabell/InntektsmeldingEntitet.kt @@ -1,4 +1,4 @@ -package no.nav.helsearbeidsgiver.inntektsmelding.db.config +package no.nav.helsearbeidsgiver.inntektsmelding.db.tabell import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.Inntektsmelding import no.nav.helsearbeidsgiver.felles.EksternInntektsmelding diff --git a/db/src/main/resources/db/migration/V11__aapen_inntektsmelding.sql b/db/src/main/resources/db/migration/V11__aapen_inntektsmelding.sql new file mode 100644 index 0000000000..120551fd42 --- /dev/null +++ b/db/src/main/resources/db/migration/V11__aapen_inntektsmelding.sql @@ -0,0 +1,10 @@ +CREATE TABLE aapen_inntektsmelding +( + id BIGSERIAL NOT NULL PRIMARY KEY, + aapen_id UUID NOT NULL, + inntektsmelding JSONB NOT NULL, + journalpost_id TEXT UNIQUE, + opprettet TIMESTAMP NOT NULL DEFAULT now() +); + +CREATE INDEX aapen_id_index ON aapen_inntektsmelding(aapen_id); diff --git a/db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/LocalApp.kt b/db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/LocalApp.kt deleted file mode 100644 index 2b885f2507..0000000000 --- a/db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/LocalApp.kt +++ /dev/null @@ -1,12 +0,0 @@ -package no.nav.helsearbeidsgiver.inntektsmelding.db - -import no.nav.helsearbeidsgiver.felles.app.LocalApp -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.DatabaseConfig -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.mapHikariConfig - -fun main() { - val env = LocalApp().setupEnvironment("im-db", 9090) - val rapid = buildApp(mapHikariConfig(DatabaseConfig("127.0.0.1", "5432", "im_db", "postgres", "test")), env) - - rapid.start() -} diff --git a/db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/RepositoryTest.kt b/db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/RepositoryTest.kt index 38b66d5ecd..ddf430c87b 100644 --- a/db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/RepositoryTest.kt +++ b/db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/RepositoryTest.kt @@ -9,8 +9,8 @@ import io.kotest.matchers.nulls.shouldBeNull import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.ForespoerselEntitet -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.InntektsmeldingEntitet +import no.nav.helsearbeidsgiver.inntektsmelding.db.tabell.ForespoerselEntitet +import no.nav.helsearbeidsgiver.inntektsmelding.db.tabell.InntektsmeldingEntitet import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Expression import org.jetbrains.exposed.sql.Op @@ -24,21 +24,20 @@ import java.util.UUID class TestRepo(private val db: Database) { - fun hentRecordFraInntektsmelding(forespørselId: String): ResultRow? { - return transaction(db) { - InntektsmeldingEntitet.run { - select { (forespoerselId eq forespørselId) } + fun hentRecordFraInntektsmelding(forespoerselId: UUID): ResultRow? = + transaction(db) { + InntektsmeldingEntitet.select { + InntektsmeldingEntitet.forespoerselId eq forespoerselId.toString() }.firstOrNull() } - } - fun hentRecordFraForespoersel(forespørselId: String): ResultRow? { - return transaction(db) { - ForespoerselEntitet.run { - select { (forespoerselId eq forespørselId) } - }.firstOrNull() + fun hentRecordFraForespoersel(forespoerselId: UUID): ResultRow? = + transaction(db) { + ForespoerselEntitet.select { + ForespoerselEntitet.forespoerselId eq forespoerselId.toString() + } + .firstOrNull() } - } } class RepositoryTest : FunSpecWithDb(listOf(InntektsmeldingEntitet, ForespoerselEntitet), { db -> @@ -145,7 +144,7 @@ class RepositoryTest : FunSpecWithDb(listOf(InntektsmeldingEntitet, Forespoersel foresporselRepo.lagreForespoersel(forespoerselId.toString(), ORGNR) inntektsmeldingRepo.lagreInntektsmelding(forespoerselId.toString(), DOK_1) inntektsmeldingRepo.oppdaterJournalpostId(forespoerselId, JOURNALPOST_1) - val record = testRepo.hentRecordFraInntektsmelding(forespoerselId.toString()) + val record = testRepo.hentRecordFraInntektsmelding(forespoerselId) record.shouldNotBeNull() val journalPostId = record.getOrNull(InntektsmeldingEntitet.journalpostId) journalPostId.shouldNotBeNull() @@ -265,11 +264,11 @@ class RepositoryTest : FunSpecWithDb(listOf(InntektsmeldingEntitet, Forespoersel InntektsmeldingEntitet.selectAll().toList() }.shouldBeEmpty() - val forespoerselId = "abc-456" + val forespoerselId = UUID.randomUUID() val SAK_ID_1 = "sak1-1" - foresporselRepo.lagreForespoersel(forespoerselId, ORGNR) - foresporselRepo.oppdaterSakId(forespoerselId, SAK_ID_1) + foresporselRepo.lagreForespoersel(forespoerselId.toString(), ORGNR) + foresporselRepo.oppdaterSakId(forespoerselId.toString(), SAK_ID_1) val record = testRepo.hentRecordFraForespoersel(forespoerselId) record.shouldNotBeNull() val sakId = record.getOrNull(ForespoerselEntitet.sakId) @@ -282,11 +281,11 @@ class RepositoryTest : FunSpecWithDb(listOf(InntektsmeldingEntitet, Forespoersel InntektsmeldingEntitet.selectAll().toList() }.shouldBeEmpty() - val forespoerselId = "abc-456" + val forespoerselId = UUID.randomUUID() val OPPGAVE_ID_1 = "oppg-1" - foresporselRepo.lagreForespoersel(forespoerselId, ORGNR) - foresporselRepo.oppdaterOppgaveId(forespoerselId, OPPGAVE_ID_1) + foresporselRepo.lagreForespoersel(forespoerselId.toString(), ORGNR) + foresporselRepo.oppdaterOppgaveId(forespoerselId.toString(), OPPGAVE_ID_1) val rad = testRepo.hentRecordFraForespoersel(forespoerselId) rad.shouldNotBeNull() val oppgaveId = rad.getOrNull(ForespoerselEntitet.oppgaveId) diff --git a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/EventTypes.kt b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/EventTypes.kt index 43b666394d..96cfb9a3dd 100644 --- a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/EventTypes.kt +++ b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/EventTypes.kt @@ -12,17 +12,23 @@ enum class BehovType { ARBEIDSGIVERE, TILGANGSKONTROLL, HENT_TRENGER_IM, // TODO: SPLEIS_FORESPOERSEL eller SPLEIS_FORESPOERSEL_DETALJER?? + PERSISTER_IM, HENT_PERSISTERT_IM, + LAGRE_AAPEN_IM, + HENT_AAPEN_IM, + LAGRE_JOURNALPOST_ID, LAGRE_FORESPOERSEL, DISTRIBUER_IM, + NOTIFIKASJON_HENT_ID, OPPRETT_SAK, SLETT_SAK, PERSISTER_SAK_ID, OPPRETT_OPPGAVE, PERSISTER_OPPGAVE_ID, + HENT_IM_ORGNR, HENT_EKSTERN_INNTEKTSMELDING, LAGRE_EKSTERN_INNTEKTSMELDING, @@ -57,6 +63,7 @@ enum class EventName { SAK_OPPRETT_REQUESTED, SAK_OPPRETTET, SAK_FERDIGSTILT, + MANUELL_OPPRETT_SAK_REQUESTED, MANUELL_SLETT_SAK_REQUESTED, diff --git a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/loeser/ObjectRiver.kt b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/loeser/ObjectRiver.kt index 9fe4a93d2c..64667b3786 100644 --- a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/loeser/ObjectRiver.kt +++ b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/loeser/ObjectRiver.kt @@ -36,7 +36,7 @@ import no.nav.helsearbeidsgiver.utils.log.sikkerLogger * height = Key.HEIGHT.lesOrNull(Int.serializer(), json) * ) * - * override fun LotrCharacter.haandter(): Map { + * override fun LotrCharacter.haandter(json: Map): Map { * val favouriteFood = when (name) { * "Frodo" -> "\uD83C\uDF53" * "Sam" -> "\uD83E\uDD54" @@ -72,9 +72,11 @@ abstract class ObjectRiver { * * @param json innkommende melding. * - * @return Verdi lest fra [json]. Brukes som input i [haandter]. + * @return + * Verdi lest fra [json]. Brukes som input i [haandter]. + * Returneres '`null`' så vil melding ignoreres. */ - protected abstract fun les(json: Map): Melding + protected abstract fun les(json: Map): Melding? /** * Riverens hovedfunksjon. Agerer på innkommende melding. @@ -86,7 +88,7 @@ abstract class ObjectRiver { * Utgående melding som skal publiseres når innkommende melding er ferdig prosessert. * Returneres '`null`' så vil ingen utgående melding publiseres. */ - protected abstract fun Melding.haandter(): Map? + protected abstract fun Melding.haandter(json: Map): Map? /** * Kalles ved exception under [haandter]. @@ -95,7 +97,7 @@ abstract class ObjectRiver { * Utgående melding som skal publiseres når feil er ferdig prosessert. * Default implementasjon returnerer '`null`', som betyr at ingen utgående melding publiseres. */ - protected open fun Throwable.haandterFeil(json: Map): Map? { + protected open fun Melding.haandterFeil(json: Map, error: Throwable): Map? { "Ukjent feil.".also { logger.error(it) sikkerLogger.error(it, this) @@ -107,12 +109,14 @@ abstract class ObjectRiver { internal fun lesOgHaandter(json: Map): Map? { val innkommende = runCatching { les(json) }.getOrNull() - val utgaaende = runCatching { - innkommende?.haandter() - } - .getOrElse { - it.haandterFeil(json) + val utgaaende = innkommende?.let { + runCatching { + it.haandter(json) } + .getOrElse { e -> + it.haandterFeil(json, e) + } + } if (utgaaende != null && utgaaende.isEmpty()) { "Utgående melding er tom.".also { diff --git a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/metrics/Metrics.kt b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/metrics/Metrics.kt index 24877dd335..2e327f9415 100644 --- a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/metrics/Metrics.kt +++ b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/metrics/Metrics.kt @@ -4,14 +4,27 @@ import io.prometheus.client.Summary import kotlinx.coroutines.runBlocking object Metrics { - val altinnRequest = Summary.build() + val dbAapenIm: Summary = Summary.build() + .name("simba_db_aapen_im_repo_latency_seconds") + .help("Latency (i sek.) for database 'im-db' and table 'aapen_inntektsmelding'.") + .labelNames("method") + .register() + + val altinnRequest: Summary = Summary.build() .name("simba_altinn_hent_rettighet_organisasjoner_latency_seconds") - .help("Altinn hentRettighetOrganisasjoner - latency in seconds") + .help("Latency (i sek.) for Altinn-hentRettighetOrganisasjoner.") .register() } -fun Summary.recordTime(block: suspend () -> T): T { - val requestTimer = startTimer() +/** Bruk av [label] krever at `labelNames` er satt på [Summary]. */ +fun Summary.recordTime(label: String? = null, block: suspend () -> T): T { + val requestTimer: Summary.Timer = + if (label == null) { + startTimer() + } else { + labels(label).startTimer() + } + return runBlocking { block() } .also { requestTimer.observeDuration() diff --git a/integrasjonstest/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/App.kt b/integrasjonstest/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/App.kt index fdcdd8e756..079fe09676 100644 --- a/integrasjonstest/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/App.kt +++ b/integrasjonstest/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/App.kt @@ -1,54 +1,5 @@ package no.nav.helsearbeidsgiver.inntektsmelding.integrasjonstest -import no.nav.helse.rapids_rivers.RapidApplication -import no.nav.helse.rapids_rivers.RapidsConnection -import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore -import no.nav.helsearbeidsgiver.inntektsmelding.db.ForespoerselRepository -import no.nav.helsearbeidsgiver.inntektsmelding.db.InntektsmeldingRepository -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.Database -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.DatabaseConfig -import no.nav.helsearbeidsgiver.inntektsmelding.db.config.mapHikariConfig -import no.nav.helsearbeidsgiver.inntektsmelding.db.createDb -import no.nav.helsearbeidsgiver.inntektsmelding.innsending.createInnsending -import no.nav.helsearbeidsgiver.inntektsmelding.inntektservice.createInntektService -import no.nav.helsearbeidsgiver.inntektsmelding.tilgangservice.createTilgangService -import no.nav.helsearbeidsgiver.inntektsmelding.trengerservice.createTrengerService - fun main() { - val env = mapOf( - "KAFKA_RAPID_TOPIC" to "helsearbeidsgiver.inntektsmelding", - "KAFKA_BOOTSTRAP_SERVERS" to "PLAINTEXT://localhost:9092", - "KAFKA_CONSUMER_GROUP_ID" to "HAG" - ) - - RapidApplication - .create(env) - .buildLocalApp() - .start() + // Jeg må bare være her for at modulen skal kompilere ¯\_(ツ)_/¯ } - -fun RapidsConnection.buildLocalApp(): RapidsConnection = - also { - val redisStore = RedisStore("redis://localhost:6379/0") - val database = Database( - mapHikariConfig( - DatabaseConfig( - host = "127.0.0.1", - port = "5432", - name = "im_db", - username = "postgres", - password = "test" - ) - ) - ) - val imRepository = InntektsmeldingRepository(database.db) - val forespoerselRepository = ForespoerselRepository(database.db) - - createInnsending(redisStore) - createInntektService(redisStore) - createTilgangService(redisStore) - createTrengerService(redisStore) - - createDb(database, imRepository, forespoerselRepository) -// createForespoerselMottatt() - } diff --git a/integrasjonstest/src/main/resources/logback.xml b/integrasjonstest/src/main/resources/logback.xml deleted file mode 100644 index e08fa0f863..0000000000 --- a/integrasjonstest/src/main/resources/logback.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - %green(%d{HH:mm:ss}){faint} %cyan([%-5.5t]){faint} %highlight(%0.-5p) %yellow(%-40.40logger{39}){cyan}: [%mdc] %m%n - - - - - - - - - - - diff --git a/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/utils/EndToEndTest.kt b/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/utils/EndToEndTest.kt index e1ee002e96..ec2c888cbb 100644 --- a/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/utils/EndToEndTest.kt +++ b/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/utils/EndToEndTest.kt @@ -31,10 +31,12 @@ import no.nav.helsearbeidsgiver.inntektsmelding.brospinn.SpinnKlient import no.nav.helsearbeidsgiver.inntektsmelding.brospinn.createEksternInntektsmeldingLoeser import no.nav.helsearbeidsgiver.inntektsmelding.brospinn.createSpinnService import no.nav.helsearbeidsgiver.inntektsmelding.brreg.createBrreg +import no.nav.helsearbeidsgiver.inntektsmelding.db.AapenImRepo import no.nav.helsearbeidsgiver.inntektsmelding.db.ForespoerselRepository import no.nav.helsearbeidsgiver.inntektsmelding.db.InntektsmeldingRepository import no.nav.helsearbeidsgiver.inntektsmelding.db.config.Database -import no.nav.helsearbeidsgiver.inntektsmelding.db.createDb +import no.nav.helsearbeidsgiver.inntektsmelding.db.createDbRivers +import no.nav.helsearbeidsgiver.inntektsmelding.db.registerDbLifecycle import no.nav.helsearbeidsgiver.inntektsmelding.distribusjon.createDistribusjon import no.nav.helsearbeidsgiver.inntektsmelding.forespoerselbesvart.createForespoerselBesvartFraSimba import no.nav.helsearbeidsgiver.inntektsmelding.forespoerselbesvart.createForespoerselBesvartFraSpleis @@ -102,6 +104,7 @@ abstract class EndToEndTest : ContainerTest(), RapidsConnection.MessageListener val tilgangProducer by lazy { TilgangProducer(rapid) } val imRepository by lazy { InntektsmeldingRepository(database.db) } + val aapenImRepo by lazy { AapenImRepo(database.db) } val forespoerselRepository by lazy { ForespoerselRepository(database.db) } val altinnClient = mockk() @@ -172,7 +175,7 @@ abstract class EndToEndTest : ContainerTest(), RapidsConnection.MessageListener createAareg(aaregClient) createAltinn(altinnClient) createBrreg(brregClient, false) - createDb(database, imRepository, forespoerselRepository) + createDbRivers(imRepository, aapenImRepo, forespoerselRepository) createDistribusjon(mockk(relaxed = true)) createForespoerselBesvartFraSimba() createForespoerselBesvartFraSpleis(mockPriProducer) @@ -187,6 +190,7 @@ abstract class EndToEndTest : ContainerTest(), RapidsConnection.MessageListener createSpinnService(redisStore) createAktiveOrgnrService(redisStore) } + .registerDbLifecycle(database) .register(this) thread = thread { diff --git a/trengerservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/trengerservice/TrengerService.kt b/trengerservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/trengerservice/TrengerService.kt index 8d082d465a..e7b1a32d04 100644 --- a/trengerservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/trengerservice/TrengerService.kt +++ b/trengerservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/trengerservice/TrengerService.kt @@ -92,7 +92,7 @@ class TrengerService( sikkerLogger.info("Dispatcher for $transaksjonId with trans state 'in progress'") - if (steg1Keys.all { it in melding } && steg2Keys.none { it in melding }) { + if (steg1Keys.all(melding::containsKey) && steg2Keys.none(melding::containsKey)) { val forespoersel = Key.FORESPOERSEL_SVAR.les(TrengerInntekt.serializer(), melding) sikkerLogger.info("${simpleName()} Dispatcher VIRKSOMHET for $transaksjonId") @@ -257,7 +257,7 @@ class TrengerService( val meldingMedDefault = datafeil.associate { it.key to it.defaultVerdi } .plus(melding) - if (dataKeys.all { it in meldingMedDefault }) { + if (dataKeys.all(meldingMedDefault::containsKey)) { finalize(meldingMedDefault) } }