-
Notifications
You must be signed in to change notification settings - Fork 0
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
Dev/feilkoe headers #112
base: main
Are you sure you want to change the base?
Dev/feilkoe headers #112
Changes from 20 commits
b3867e3
501c6d8
5e59172
0bcf452
29d6b2e
f18b0bd
ba756d5
d3af0a8
0753c45
190a9d9
6617a97
c050c35
64975e1
db4d56c
9cb3a70
2621350
7d46ab0
b37844d
d7f7163
a0a5e8f
ba3fc33
1b80d83
73bf16d
007260e
225fb97
dc2e0dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,9 @@ import arrow.fx.coroutines.resourceScope | |
import io.ktor.server.application.Application | ||
import io.ktor.server.auth.authenticate | ||
import io.ktor.server.netty.Netty | ||
import io.ktor.server.routing.Route | ||
import io.ktor.server.routing.Routing | ||
import io.ktor.server.routing.get | ||
import io.ktor.server.routing.routing | ||
import io.ktor.utils.io.CancellationException | ||
import io.micrometer.prometheusmetrics.PrometheusConfig | ||
|
@@ -28,6 +31,8 @@ import no.nav.emottak.ebms.SendInClient | |
import no.nav.emottak.ebms.SmtpTransportClient | ||
import no.nav.emottak.ebms.async.configuration.Config | ||
import no.nav.emottak.ebms.async.configuration.config | ||
import no.nav.emottak.ebms.async.kafka.consumer.failedMessageQueue | ||
import no.nav.emottak.ebms.async.kafka.consumer.getRecord | ||
import no.nav.emottak.ebms.async.kafka.consumer.startPayloadReceiver | ||
import no.nav.emottak.ebms.async.kafka.consumer.startSignalReceiver | ||
import no.nav.emottak.ebms.async.kafka.producer.EbmsMessageProducer | ||
|
@@ -48,7 +53,9 @@ import no.nav.emottak.ebms.registerRootEndpoint | |
import no.nav.emottak.ebms.scopedAuthHttpClient | ||
import no.nav.emottak.ebms.sendin.SendInService | ||
import no.nav.emottak.ebms.validation.DokumentValidator | ||
import no.nav.emottak.utils.isProdEnv | ||
import org.slf4j.LoggerFactory | ||
import kotlin.uuid.ExperimentalUuidApi | ||
|
||
val log = LoggerFactory.getLogger("no.nav.emottak.ebms.async.App") | ||
|
||
|
@@ -81,6 +88,15 @@ fun main() = SuspendApp { | |
ebmsPayloadProducer = ebmsPayloadProducer | ||
) | ||
|
||
val payloadMessageProcessorProvider = payloadMessageProcessorProvider( | ||
ebmsMessageDetailsRepository = ebmsMessageDetailsRepository, | ||
dokumentValidator = dokumentValidator, | ||
processingService = processingService, | ||
ebmsSignalProducer = ebmsSignalProducer, | ||
smtpTransportClient = smtpTransportClient, | ||
payloadMessageResponder = payloadMessageResponder | ||
) | ||
|
||
result { | ||
resourceScope { | ||
launchSignalReceiver( | ||
|
@@ -90,20 +106,16 @@ fun main() = SuspendApp { | |
) | ||
launchPayloadReceiver( | ||
config = config, | ||
dokumentValidator = dokumentValidator, | ||
processingService = processingService, | ||
ebmsSignalProducer = ebmsSignalProducer, | ||
smtpTransportClient = smtpTransportClient, | ||
payloadMessageResponder = payloadMessageResponder, | ||
ebmsMessageDetailsRepository = ebmsMessageDetailsRepository | ||
payloadMessageProcessorProvider = payloadMessageProcessorProvider | ||
) | ||
|
||
server( | ||
Netty, | ||
port = 8080, | ||
module = { | ||
ebmsProviderModule( | ||
payloadRepository = payloadRepository | ||
payloadRepository = payloadRepository, | ||
payloadProcessorProvider = payloadMessageProcessorProvider | ||
) | ||
} | ||
).also { it.engineConfig.maxChunkSize = 100000 } | ||
|
@@ -119,26 +131,36 @@ fun main() = SuspendApp { | |
} | ||
} | ||
|
||
private fun CoroutineScope.launchPayloadReceiver( | ||
config: Config, | ||
fun payloadMessageProcessorProvider( | ||
ebmsMessageDetailsRepository: EbmsMessageDetailsRepository, | ||
dokumentValidator: DokumentValidator, | ||
processingService: ProcessingService, | ||
ebmsSignalProducer: EbmsMessageProducer, | ||
smtpTransportClient: SmtpTransportClient, | ||
payloadMessageResponder: PayloadMessageResponder, | ||
ebmsMessageDetailsRepository: EbmsMessageDetailsRepository | ||
payloadMessageResponder: PayloadMessageResponder | ||
|
||
): () -> PayloadMessageProcessor = { | ||
PayloadMessageProcessor( | ||
ebmsMessageDetailsRepository = ebmsMessageDetailsRepository, | ||
validator = dokumentValidator, | ||
processingService = processingService, | ||
ebmsSignalProducer = ebmsSignalProducer, | ||
smtpTransportClient = smtpTransportClient, | ||
payloadMessageResponder | ||
) | ||
} | ||
|
||
private fun CoroutineScope.launchPayloadReceiver( | ||
config: Config, | ||
payloadMessageProcessorProvider: () -> PayloadMessageProcessor | ||
) { | ||
if (config.kafkaPayloadReceiver.active) { | ||
launch(Dispatchers.IO) { | ||
val payloadMessageProcessor = PayloadMessageProcessor( | ||
validator = dokumentValidator, | ||
processingService = processingService, | ||
ebmsSignalProducer = ebmsSignalProducer, | ||
smtpTransportClient = smtpTransportClient, | ||
ebmsMessageDetailsRepository = ebmsMessageDetailsRepository, | ||
payloadMessageResponder = payloadMessageResponder | ||
startPayloadReceiver( | ||
config.kafkaPayloadReceiver.topic, | ||
config.kafka, | ||
payloadMessageProcessorProvider.invoke() | ||
) | ||
startPayloadReceiver(config.kafkaPayloadReceiver.topic, config.kafka, payloadMessageProcessor) | ||
} | ||
} | ||
} | ||
|
@@ -160,7 +182,8 @@ private fun CoroutineScope.launchSignalReceiver( | |
} | ||
|
||
fun Application.ebmsProviderModule( | ||
payloadRepository: PayloadRepository | ||
payloadRepository: PayloadRepository, | ||
payloadProcessorProvider: () -> PayloadMessageProcessor | ||
) { | ||
val appMicrometerRegistry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT) | ||
|
||
|
@@ -173,9 +196,50 @@ fun Application.ebmsProviderModule( | |
registerHealthEndpoints() | ||
registerPrometheusEndpoint(appMicrometerRegistry) | ||
registerNavCheckStatus() | ||
|
||
if (!isProdEnv()) { | ||
simulateError() | ||
} | ||
retryErrors(payloadProcessorProvider) | ||
authenticate(AZURE_AD_AUTH) { | ||
getPayloads(payloadRepository) | ||
} | ||
} | ||
} | ||
|
||
const val RETRY_LIMIT = "retryLimit" | ||
|
||
@OptIn(ExperimentalUuidApi::class) | ||
fun Routing.retryErrors( | ||
payloadMessageProcessorProvider: () -> PayloadMessageProcessor | ||
): Route = | ||
get("/api/retry/{$RETRY_LIMIT}") { | ||
resourceScope { | ||
CoroutineScope(Dispatchers.IO).launch { | ||
if (config().kafkaErrorQueue.active) { | ||
failedMessageQueue.receive( | ||
payloadMessageProcessorProvider.invoke(), | ||
limit = (call.parameters[RETRY_LIMIT] as String).toInt() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Litt flisespikkeri, men syntes koden blir mer ryddig hvis du løfter There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hvorfor synes du det? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tipper fordi blir koden mer verbose. I prinsipp er jeg helt enig, men akkurat i dette eksemplet tenker jeg at det ikke gir så mye verdi å bruke mer tid på denne linjen |
||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
const val KAFKA_OFFSET = "offset" | ||
|
||
fun Route.simulateError(): Route = get("/api/forceretry/{$KAFKA_OFFSET}") { | ||
resourceScope { | ||
CoroutineScope(Dispatchers.IO).launch { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Samme som over |
||
if (config().kafkaErrorQueue.active) { | ||
val record = getRecord( | ||
config() | ||
.kafkaPayloadReceiver.topic, | ||
config().kafka | ||
.copy(groupId = "ebms-provider-retry"), | ||
(call.parameters[KAFKA_OFFSET] as String).toLong() | ||
) | ||
failedMessageQueue.send(record = record ?: throw Exception("No Record found. Offset: ${call.parameters[KAFKA_OFFSET]}")) | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Når du oppretter et
CoroutineScope
her på denne måten er det greit å være klar over at dette blir et helt frittstående scope som ikke er linket tilresourceScope
'et. Joda, det vil bli tatt ned når jvm'en shutter ned, men ikke på en clean måte.Jeg snakket jo litt om dette for noen uker siden (i en delingstime) hvordan en kan linke frittstående scopes til omsluttende ressurs-scope så scopet i seg selv blir en ressurs / avhengighet på lik linje med alle andre ressurser og avhengigheter. Fordelen er selvsagt at scopet blir inkludert i livssyklusen til ressurs-scopet i
SuspendApp
og tatt ned og opprettet på en clean måte.Her er linken til utility funksjonen som gjør dette for deg: https://github.com/navikt/smtp-transport/blob/main/src/main/kotlin/no/nav/emottak/util/ResourceUtil.kt
Sikkert noe vi burde putte inn i felles-biblioteket på et tidspunkt.