Skip to content

Commit a4e5b96

Browse files
committed
Ny app for min-side varsler
1 parent e8f1639 commit a4e5b96

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2380
-2
lines changed
+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: Min Side Varsler
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- dev/*
8+
paths:
9+
- 'apps/min-side-varsler/**'
10+
- 'lib/**'
11+
- 'domain/**'
12+
- '.github/workflows/min-side-varsler.yaml'
13+
- 'gradle/**'
14+
- 'settings.gradle.kts'
15+
- 'gradle.properties'
16+
- 'gradlew'
17+
- 'gradlew.bat'
18+
19+
env:
20+
MODULE: min-side-varsler
21+
IMAGE: europe-north1-docker.pkg.dev/${{ vars.NAIS_MANAGEMENT_PROJECT_ID }}/paw/paw-arbeidssoekerregisteret-min-side-varsler
22+
jobs:
23+
build:
24+
name: Build
25+
runs-on: ubuntu-latest
26+
timeout-minutes: 10
27+
permissions:
28+
contents: read
29+
id-token: write
30+
packages: write
31+
outputs:
32+
image: ${{ steps.docker-build-push.outputs.image }}
33+
steps:
34+
- name: Checkout
35+
uses: actions/checkout@v4
36+
- name: Setup Java
37+
uses: actions/setup-java@v4
38+
with:
39+
java-version: 21
40+
distribution: temurin
41+
cache: gradle
42+
- name: Set version
43+
run: echo "VERSION=$(date +'%y.%m.%d').${{ github.run_number }}-${{ github.run_attempt }}" >> $GITHUB_ENV
44+
- name: Login GAR
45+
uses: nais/login@v0
46+
with:
47+
project_id: ${{ vars.NAIS_MANAGEMENT_PROJECT_ID }}
48+
identity_provider: ${{ secrets.NAIS_WORKLOAD_IDENTITY_PROVIDER }}
49+
team: paw
50+
- name: Build with Gradle
51+
id: docker-build-push
52+
working-directory: ./
53+
run: |
54+
echo "image=${{ env.IMAGE }}:${{ env.VERSION }}" >> $GITHUB_OUTPUT
55+
echo -Pversion=${{ env.VERSION }} -Pimage=${{ env.IMAGE }} :apps:${{ env.MODULE }}:build :apps:${{ env.MODULE }}:jib
56+
./gradlew -Pversion=${{ env.VERSION }} -Pimage=${{ env.IMAGE }} :apps:${{ env.MODULE }}:build :apps:${{ env.MODULE }}:jib
57+
echo "DIGEST=$(cat apps/${{ env.MODULE }}/build/jib-image.digest)" >> $GITHUB_ENV
58+
env:
59+
ORG_GRADLE_PROJECT_githubPassword: ${{ secrets.GITHUB_TOKEN }}
60+
- name: Attest and sign image
61+
uses: nais/[email protected]
62+
with:
63+
image_ref: ${{ env.IMAGE }}@${{ env.DIGEST }}
64+
65+
deploy-dev:
66+
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/dev')
67+
name: Deploy to dev-gcp
68+
needs:
69+
- build
70+
permissions:
71+
contents: read
72+
id-token: write
73+
runs-on: ubuntu-latest
74+
steps:
75+
- name: Checkout
76+
uses: actions/checkout@v4
77+
- name: Deploy to GCP
78+
uses: nais/deploy/actions/deploy@v2
79+
env:
80+
CLUSTER: dev-gcp
81+
RESOURCE: ./apps/${{ env.MODULE }}/nais/nais-dev.yaml
82+
VAR: image=${{ needs.build.outputs.image }},kafka=nav-dev
83+
84+
# deploy-prod:
85+
# if: github.ref == 'refs/heads/main'
86+
# name: Deploy to prod-gcp
87+
# needs:
88+
# - build
89+
# - deploy-dev
90+
# permissions:
91+
# contents: read
92+
# id-token: write
93+
# runs-on: ubuntu-latest
94+
# steps:
95+
# - name: Checkout
96+
# uses: actions/checkout@v4
97+
# - name: Deploy to GCP
98+
# uses: nais/deploy/actions/deploy@v2
99+
# env:
100+
# TEAM: paw
101+
# CLUSTER: prod-gcp
102+
# RESOURCE: ./apps/${{ env.MODULE }}/nais/nais-prod.yaml
103+
# VAR: image=${{ needs.build.outputs.image }},kafka=nav-prod

apps/min-side-varsler/README.md

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Min Side Varsler
2+
3+
## Varsler
4+
Team Min Side sin [system-dok](https://navikt.github.io/tms-dokumentasjon)
5+
6+
Varsler opprettes ved å sende en varselmelding på Kafka-topic `min-side.aapen-brukervarsel-v1`.
7+
8+
### Varseltyper
9+
Det finnes tre typer varsler:
10+
* **beskjed** - Enkel informasjon til brukere
11+
* **oppgave** - Brukere må utføre noe
12+
* **innboks** - Varsle om melding i digital innboks
13+
14+
### Varselhendelser
15+
Når tilstand endres for et varsel hos Min Side så opprettes det en varselhendelsemelding på Kafka-topic
16+
`min-side.aapen-varsel-hendelse-v1`.
17+
18+
Det finnes fire typer varselhendelser:
19+
* **opprettet** - TMS har mottat varselmeldingen og lagret den i sin database
20+
* **inaktivert** - Varsel er inaktivert av bruker eller produsent
21+
* **slettet** - Varsel er slettet fra databasen til TMS
22+
* **eksternStatusOppdatert** - Kommer kun om varsel også har blitt send som SMS/Epost, og status for utsending har endret seg
23+
24+
```mermaid
25+
stateDiagram-v2
26+
[*] --> opprettet
27+
opprettet --> inaktivert
28+
opprettet --> eksternStatusOppdatert
29+
eksternStatusOppdatert --> inaktivert
30+
inaktivert --> slettet
31+
slettet --> [*]
32+
```
33+
34+
Ved ekstern varsling via SMS/Epost så inneholder varselhendelsen også en status:
35+
* **venter** - Eksternt varsel er klar for utsending
36+
* **bestilt** - Eksternt varsel er oversendt til Altinn
37+
* **sendt** - Eksternt varsel er bekreftet sendt
38+
* **feilet** - Eksternt varsel feilet ved utsending
39+
* **ferdigstilt** - Eksternt varsel er fullført
40+
41+
```mermaid
42+
stateDiagram-v2
43+
[*] --> venter
44+
venter --> bestilt
45+
bestilt --> sendt
46+
sendt --> ferdigstilt
47+
bestilt --> feilet
48+
feilet --> feilet: renotifikasjon
49+
feilet --> sendt
50+
feilet --> ferdigstilt: inaktivert
51+
ferdigstilt --> [*]
52+
```
+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
plugins {
2+
kotlin("jvm")
3+
id("jib-distroless")
4+
}
5+
6+
val jvmMajorVersion: String by project
7+
8+
dependencies {
9+
// Project
10+
implementation(project(":lib:hoplite-config"))
11+
implementation(project(":lib:logging"))
12+
implementation(project(":lib:serialization"))
13+
implementation(project(":lib:error-handling"))
14+
implementation(project(":lib:metrics"))
15+
implementation(project(":lib:database"))
16+
implementation(project(":lib:kafka-streams"))
17+
implementation(project(":domain:bekreftelse-interne-hendelser"))
18+
implementation(project(":domain:main-avro-schema"))
19+
20+
// Ktor
21+
implementation(libs.bundles.ktorServerWithNettyAndMicrometer)
22+
23+
// Jackson
24+
implementation(libs.jackson.kotlin)
25+
implementation(libs.jackson.datatypeJsr310)
26+
27+
// Logging
28+
implementation(libs.logbackClassic)
29+
implementation(libs.logstashLogbackEncoder)
30+
31+
// Observability
32+
implementation(libs.micrometer.registryPrometheus)
33+
implementation(libs.opentelemetry.api)
34+
implementation(libs.opentelemetry.annotations)
35+
36+
// Database
37+
implementation(libs.exposed.jdbc)
38+
implementation(libs.exposed.javaTime)
39+
implementation(libs.database.hikari.connectionPool)
40+
implementation(libs.database.postgres.driver)
41+
implementation(libs.database.flyway.postgres)
42+
43+
// Kafka
44+
implementation(libs.kafka.clients)
45+
implementation(libs.kafka.streams.core)
46+
implementation(libs.avro.kafkaStreamsSerde)
47+
48+
// Utils
49+
implementation(libs.arrow.core.core)
50+
implementation(libs.hoplite.yaml)
51+
52+
// Nav
53+
implementation(libs.nav.common.log)
54+
implementation(libs.nav.tms.varsel.kotlinBuilder)
55+
56+
// Testing
57+
testImplementation(project(":test:test-data-lib"))
58+
testImplementation(project(":lib:kafka-key-generator-client"))
59+
testImplementation(libs.bundles.testLibsWithUnitTesting)
60+
testImplementation(libs.kafka.streams.test)
61+
testImplementation(libs.database.h2)
62+
}
63+
64+
tasks.withType<Test>().configureEach {
65+
useJUnitPlatform()
66+
}
+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
apiVersion: nais.io/v1alpha1
2+
kind: Application
3+
metadata:
4+
name: paw-arbeidssoekerregisteret-min-side-varsler
5+
namespace: paw
6+
labels:
7+
team: paw
8+
spec:
9+
image: {{ image }}
10+
port: 8080
11+
replicas:
12+
min: 1
13+
max: 1
14+
resources:
15+
limits:
16+
memory: 1024Mi
17+
requests:
18+
cpu: 200m
19+
memory: 256Mi
20+
env:
21+
- name: KAFKA_BEKREFTELSE_STREAM_SUFFIX
22+
value: bekreftelse-beta-v1
23+
- name: KAFKA_VARSEL_HENDELSE_STREAM_SUFFIX
24+
value: varsel-hendelser-beta-v1
25+
- name: KAFKA_PAW_ARBEIDSOKERPERIODE_TOPIC
26+
value: paw.arbeidssokerperioder-v1
27+
- name: KAFKA_PAW_ARBEIDSOKER_BEKREFTELSE_HENDELSESLOGG_TOPIC
28+
value: paw.arbeidssoker-bekreftelse-hendelseslogg-beta-v2
29+
- name: KAFKA_TMS_AAPEN_BRUKERVARSEL_TOPIC
30+
value: min-side.aapen-brukervarsel-v1
31+
- name: KAFKA_TMS_AAPEN_VARSEL_HENDELSE_TOPIC
32+
value: min-side.aapen-varsel-hendelse-v1
33+
- name: VARSEL_LINK
34+
value: https://www.ansatt.dev.nav.no/arbeidssoekerregisteret/bekreftelse
35+
liveness:
36+
path: /internal/isAlive
37+
initialDelay: 10
38+
readiness:
39+
path: /internal/isReady
40+
initialDelay: 10
41+
azure:
42+
application:
43+
enabled: true
44+
prometheus:
45+
enabled: true
46+
path: /internal/metrics
47+
observability:
48+
autoInstrumentation:
49+
enabled: true
50+
runtime: java
51+
kafka:
52+
pool: {{ kafka }}
53+
streams: true
54+
gcp:
55+
sqlInstances:
56+
- type: POSTGRES_17
57+
tier: db-f1-micro
58+
databases:
59+
- name: pawminsidevarsler
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package no.nav.paw.arbeidssoekerregisteret
2+
3+
import io.ktor.server.application.Application
4+
import io.ktor.server.engine.addShutdownHook
5+
import io.ktor.server.engine.embeddedServer
6+
import io.ktor.server.netty.Netty
7+
import io.micrometer.core.instrument.binder.kafka.KafkaStreamsMetrics
8+
import no.nav.paw.arbeidssoekerregisteret.context.ApplicationContext
9+
import no.nav.paw.arbeidssoekerregisteret.plugin.configureRouting
10+
import no.nav.paw.config.env.appNameOrDefaultForLocal
11+
import no.nav.paw.database.plugin.installDatabasePlugin
12+
import no.nav.paw.kafka.plugin.installKafkaStreamsPlugins
13+
import no.nav.paw.logging.logger.buildApplicationLogger
14+
import no.nav.paw.metrics.plugin.installMetricsPlugin
15+
16+
fun main() {
17+
val logger = buildApplicationLogger
18+
19+
val applicationContext = ApplicationContext.build()
20+
val appName = applicationContext.serverConfig.runtimeEnvironment.appNameOrDefaultForLocal()
21+
22+
with(applicationContext.serverConfig) {
23+
logger.info("Starter $appName med hostname $host og port $port")
24+
25+
embeddedServer(factory = Netty, port = port) {
26+
module(applicationContext)
27+
}.apply {
28+
addShutdownHook {
29+
logger.info("Avslutter $appName")
30+
stop(gracePeriodMillis, timeoutMillis)
31+
}
32+
start(wait = true)
33+
}
34+
}
35+
}
36+
37+
fun Application.module(applicationContext: ApplicationContext) {
38+
with(applicationContext) {
39+
val additionalMeterBinders = kafkaStreamsList.map { KafkaStreamsMetrics(it) }
40+
installMetricsPlugin(prometheusMeterRegistry, additionalMeterBinders)
41+
installDatabasePlugin(dataSource)
42+
installKafkaStreamsPlugins(kafkaStreamsList, kafkaStreamsShutdownTimeout)
43+
configureRouting(healthIndicatorRepository, prometheusMeterRegistry)
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package no.nav.paw.arbeidssoekerregisteret.config
2+
3+
import java.time.Duration
4+
5+
const val KAFKA_TOPICS_CONFIG = "kafka_topology_config.toml"
6+
7+
data class KafkaTopologyConfig(
8+
val shutdownTimeout: Duration = Duration.ofSeconds(5),
9+
val bekreftelseStreamSuffix: String,
10+
val varselHendelseStreamSuffix: String,
11+
val periodeTopic: String,
12+
val bekreftelseHendelseTopic: String,
13+
val tmsVarselTopic: String,
14+
val tmsVarselHendelseTopic: String
15+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package no.nav.paw.arbeidssoekerregisteret.config
2+
3+
import no.nav.tms.varsel.action.EksternKanal
4+
import java.net.URI
5+
6+
const val MIN_SIDE_VARSEL_CONFIG = "min_side_varsel_config.yaml"
7+
8+
data class MinSideVarselConfig(
9+
val link: URI,
10+
val prefererteKanaler: List<EksternKanal>,
11+
val standardSpraak: Spraakkode,
12+
val tekster: List<MinSideTekst>
13+
) {
14+
init {
15+
requireNotNull(tekster.find { it.spraak == standardSpraak }) {
16+
"Ingen av tekstene har språk $standardSpraak som er satt som standard språk"
17+
}
18+
require(prefererteKanaler.isNotEmpty()) { "Ingen kanaler konfigurert" }
19+
}
20+
}
21+
22+
23+
data class Spraakkode(
24+
/**
25+
* Språkkode i henhold til ISO-639-1
26+
*/
27+
val kode: String
28+
) {
29+
init {
30+
require(kode.length == 2) { "Språkkode må være to bokstaver (ISO-639-1)" }
31+
}
32+
}
33+
34+
data class MinSideTekst(
35+
val spraak: Spraakkode,
36+
val tekst: String
37+
)

0 commit comments

Comments
 (0)