|
1 | 1 | package no.nav.paw.kafkakeymaintenance
|
2 | 2 |
|
| 3 | +import arrow.core.partially1 |
3 | 4 | import io.micrometer.prometheusmetrics.PrometheusConfig
|
4 | 5 | import io.micrometer.prometheusmetrics.PrometheusMeterRegistry
|
| 6 | +import no.nav.paw.arbeidssokerregisteret.intern.v1.HendelseSerializer |
5 | 7 | import no.nav.paw.config.hoplite.loadNaisOrLocalConfiguration
|
6 |
| -import no.nav.paw.config.kafka.* |
7 |
| -import no.nav.paw.health.model.HealthStatus |
8 |
| -import no.nav.paw.health.model.LivenessHealthIndicator |
9 |
| -import no.nav.paw.health.model.ReadinessHealthIndicator |
| 8 | +import no.nav.paw.config.kafka.KAFKA_CONFIG_WITH_SCHEME_REG |
| 9 | +import no.nav.paw.config.kafka.KafkaFactory |
10 | 10 | import no.nav.paw.health.repository.HealthIndicatorRepository
|
11 | 11 | import no.nav.paw.kafkakeygenerator.client.createKafkaKeyGeneratorClient
|
12 | 12 | import no.nav.paw.kafkakeymaintenance.db.DatabaseConfig
|
13 | 13 | import no.nav.paw.kafkakeymaintenance.db.dataSource
|
14 | 14 | import no.nav.paw.kafkakeymaintenance.db.migrateDatabase
|
15 |
| -import no.nav.paw.kafkakeymaintenance.kafka.Topic |
16 |
| -import no.nav.paw.kafkakeymaintenance.kafka.initHwm |
17 |
| -import no.nav.paw.kafkakeymaintenance.kafka.txContext |
18 |
| -import no.nav.paw.kafkakeymaintenance.pdlprocessor.AktorTopologyConfig |
| 15 | +import no.nav.paw.kafkakeymaintenance.kafka.topic |
| 16 | +import no.nav.paw.kafkakeymaintenance.pdlprocessor.AktorConfig |
| 17 | +import no.nav.paw.kafkakeymaintenance.pdlprocessor.DbReaderContext |
| 18 | +import no.nav.paw.kafkakeymaintenance.pdlprocessor.DbReaderTask |
19 | 19 | import no.nav.paw.kafkakeymaintenance.pdlprocessor.functions.hentAlias
|
20 |
| -import no.nav.paw.kafkakeymaintenance.perioder.consume |
| 20 | +import no.nav.paw.kafkakeymaintenance.pdlprocessor.sendSync |
21 | 21 | import no.nav.paw.kafkakeymaintenance.perioder.dbPerioder
|
| 22 | +import org.apache.kafka.common.serialization.LongSerializer |
22 | 23 | import org.jetbrains.exposed.sql.Database
|
23 |
| -import org.jetbrains.exposed.sql.transactions.transaction |
24 | 24 | import org.slf4j.LoggerFactory
|
25 |
| -import java.util.concurrent.CompletableFuture.runAsync |
| 25 | +import java.time.Duration |
| 26 | +import java.util.concurrent.LinkedBlockingQueue |
| 27 | +import java.util.concurrent.ThreadPoolExecutor |
| 28 | +import java.util.concurrent.TimeUnit |
26 | 29 | import java.util.concurrent.atomic.AtomicBoolean
|
| 30 | +import kotlin.system.exitProcess |
27 | 31 |
|
28 | 32 | fun main() {
|
29 | 33 | val applicationContext = ApplicationContext(
|
30 |
| - consumerVersion = PERIODE_CONSUMER_GROUP_VERSION, |
| 34 | + periodeConsumerVersion = PERIODE_CONSUMER_GROUP_VERSION, |
| 35 | + aktorConsumerVersion = AKTOR_CONSUMER_GROUP_VERSION, |
31 | 36 | logger = LoggerFactory.getLogger("app"),
|
32 | 37 | meterRegistry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT),
|
33 | 38 | shutdownCalled = AtomicBoolean(false)
|
34 | 39 | )
|
35 |
| - Runtime.getRuntime().addShutdownHook( Thread { applicationContext.shutdownCalled.set(true) }) |
| 40 | + Runtime.getRuntime().addShutdownHook(Thread { applicationContext.eventOccured(ShutdownSignal("Shutdown hook")) }) |
36 | 41 | val healthIndicatorRepository = HealthIndicatorRepository()
|
37 | 42 | with(loadNaisOrLocalConfiguration<DatabaseConfig>("database_configuration.toml").dataSource()) {
|
38 | 43 | migrateDatabase(this)
|
39 | 44 | Database.connect(this)
|
40 | 45 | }
|
41 |
| - val (hwmRebalacingListener, periodeSequence) = with(KafkaFactory(loadNaisOrLocalConfiguration(KAFKA_CONFIG_WITH_SCHEME_REG))) { |
42 |
| - initPeriodeConsumer( |
43 |
| - periodeTopic = PERIODE_TOPIC, |
44 |
| - applicationContext = applicationContext |
45 |
| - ) |
46 |
| - } |
47 |
| - val consumerLivenessHealthIndicator = healthIndicatorRepository.addLivenessIndicator( |
48 |
| - LivenessHealthIndicator(HealthStatus.UNHEALTHY) |
| 46 | + val kafkaFactory = KafkaFactory(loadNaisOrLocalConfiguration(KAFKA_CONFIG_WITH_SCHEME_REG)) |
| 47 | + val periodeConsumer = kafkaFactory.initPeriodeConsumer( |
| 48 | + healthIndicatorRepository = healthIndicatorRepository, |
| 49 | + periodeTopic = PERIODE_TOPIC, |
| 50 | + applicationContext = applicationContext |
49 | 51 | )
|
50 |
| - val consumerReadinessHealthIndicator = healthIndicatorRepository.addReadinessIndicator(ReadinessHealthIndicator()) |
51 |
| - transaction { |
52 |
| - txContext(applicationContext)().initHwm(Topic(PERIODE_TOPIC), 6) |
53 |
| - } |
54 |
| - runAsync { |
55 |
| - consumerReadinessHealthIndicator.setHealthy() |
56 |
| - consumerLivenessHealthIndicator.setHealthy() |
57 |
| - periodeSequence.consume(txContext(applicationContext)) |
58 |
| - }.handle { _, throwable -> |
59 |
| - throwable?.also { applicationContext.logger.error("Consumer task failed", throwable) } |
60 |
| - applicationContext.shutdownCalled.set(true) |
61 |
| - consumerReadinessHealthIndicator.setUnhealthy() |
62 |
| - consumerLivenessHealthIndicator.setUnhealthy() |
63 |
| - } |
64 |
| - applicationContext.logger.info("Applikasjonen er startet, consumer: {}", hwmRebalacingListener.currentlyAssignedPartitions) |
| 52 | + val aktorConsumer = kafkaFactory.initAktorConsumer( |
| 53 | + healthIndicatorRepository = healthIndicatorRepository, |
| 54 | + aktorTopic = AKTOR_TOPIC, |
| 55 | + applicationContext = applicationContext |
| 56 | + ) |
| 57 | + val producer = kafkaFactory.createProducer( |
| 58 | + clientId = "key-maintenance-producer", |
| 59 | + keySerializer = LongSerializer::class, |
| 60 | + valueSerializer = HendelseSerializer::class |
| 61 | + ) |
| 62 | + val executor = ThreadPoolExecutor(4, 4, 10L, TimeUnit.SECONDS, LinkedBlockingQueue()) |
| 63 | + val periodeTask = periodeConsumer.run(executor) |
| 64 | + val aktorTask = aktorConsumer.run(executor) |
| 65 | + val aktorConfig = loadNaisOrLocalConfiguration<AktorConfig>(AktorConfig.configFile) |
| 66 | + val antallHendelsePartisjoner = producer.partitionsFor(aktorConfig.hendelseloggTopic).size |
| 67 | + val kafkaKeysClient = createKafkaKeyGeneratorClient() |
| 68 | + val dbReaderTask = DbReaderTask( |
| 69 | + healthIndicatorRepository = healthIndicatorRepository, |
| 70 | + applicationContext = applicationContext, |
| 71 | + dbReaderContext = DbReaderContext( |
| 72 | + aktorConfig = aktorConfig, |
| 73 | + receiver = producer::sendSync.partially1(topic(aktorConfig.aktorTopic)), |
| 74 | + perioder = dbPerioder(applicationContext), |
| 75 | + hentAlias = kafkaKeysClient::hentAlias.partially1(antallHendelsePartisjoner), |
| 76 | + aktorDeSerializer = kafkaFactory.kafkaAvroDeSerializer() |
| 77 | + ) |
| 78 | + ).run(executor) |
| 79 | + |
| 80 | + applicationContext.logger.info("Applikasjonen er startet") |
65 | 81 | initKtor(
|
66 | 82 | healthIndicatorRepository = healthIndicatorRepository,
|
67 | 83 | prometheusMeterRegistry = applicationContext.meterRegistry
|
68 |
| - ).start(wait = true) |
69 |
| - applicationContext.shutdownCalled.set(true) |
70 |
| - applicationContext.logger.info("Applikasjonen er stoppet") |
| 84 | + ).start(wait = false) |
| 85 | + awaitShutdownSignalOrError(applicationContext) |
| 86 | +} |
| 87 | + |
| 88 | +fun awaitShutdownSignalOrError(applicationContext: ApplicationContext) { |
| 89 | + while (!applicationContext.shutdownCalled.get() && !Thread.currentThread().isInterrupted) { |
| 90 | + applicationContext.pollMessage(Duration.ofSeconds(2)).let { |
| 91 | + when (it) { |
| 92 | + is ErrorOccurred -> { |
| 93 | + applicationContext.shutdownCalled.set(true) |
| 94 | + Thread.sleep(Duration.ofSeconds(2)) |
| 95 | + applicationContext.logger.error("Error occurred", it.throwable) |
| 96 | + exitProcess(1) |
| 97 | + } |
| 98 | + |
| 99 | + is ShutdownSignal -> { |
| 100 | + applicationContext.shutdownCalled.set(true) |
| 101 | + applicationContext.logger.info("Shutdown signal received from ${it.source}") |
| 102 | + exitProcess(0) |
| 103 | + } |
| 104 | + |
| 105 | + is Noop -> {} |
| 106 | + } |
| 107 | + } |
| 108 | + } |
71 | 109 | }
|
0 commit comments