mirror of
https://github.com/2martens/tsw-timetable.git
synced 2026-10-17 07:57:55 +02:00
change: Remove leader election and Kafka
This commit is contained in:
@@ -40,7 +40,6 @@ spring-boot-oauth2-resource-server = { module = "org.springframework.boot:spring
|
||||
spring-boot-config = { module = "org.springframework.boot:spring-boot-configuration-processor", version.ref = "spring-boot" }
|
||||
spring-cloud = { module = "org.springframework.cloud:spring-cloud-dependencies", version.ref = "spring-cloud" }
|
||||
spring-cloud-starter = { module = "org.springframework.cloud:spring-cloud-starter" }
|
||||
spring-cloud-starter-bus-kafka = { module = "org.springframework.cloud:spring-cloud-starter-bus-kafka" }
|
||||
spring-cloud-starter-config = { module = "org.springframework.cloud:spring-cloud-starter-config" }
|
||||
spring-cloud-config-server = { module = "org.springframework.cloud:spring-cloud-config-server" }
|
||||
spring-cloud-leader-election = { module = "org.springframework.cloud:spring-cloud-kubernetes-fabric8-leader" }
|
||||
|
||||
@@ -18,6 +18,4 @@ dependencies {
|
||||
|
||||
implementation(libs.spring.openapi)
|
||||
implementation(libs.spring.boot.mongo)
|
||||
implementation(libs.spring.cloud.leader.election)
|
||||
implementation(libs.spring.cloud.starter.bus.kafka)
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
package de.twomartens.timetable.bahnApi.events
|
||||
|
||||
import org.springframework.cloud.bus.event.Destination
|
||||
import org.springframework.cloud.bus.event.PathDestinationFactory
|
||||
import org.springframework.cloud.bus.event.RemoteApplicationEvent
|
||||
import java.time.Instant
|
||||
|
||||
private const val TIMETABLE_SERVICE_NAME = "timetable"
|
||||
|
||||
class ScheduledTasksCreatedEvent private constructor(source: Instant, originService: String,
|
||||
destination: Destination)
|
||||
: RemoteApplicationEvent(source, originService, destination) {
|
||||
|
||||
private val creationTime: Instant = source
|
||||
|
||||
override fun getSource(): Instant {
|
||||
return creationTime
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val destinationFactory = PathDestinationFactory()
|
||||
|
||||
fun of(source: Instant): ScheduledTasksCreatedEvent {
|
||||
return ScheduledTasksCreatedEvent(source,
|
||||
TIMETABLE_SERVICE_NAME,
|
||||
destinationFactory.getDestination(TIMETABLE_SERVICE_NAME))
|
||||
}
|
||||
}
|
||||
}
|
||||
-2
@@ -3,9 +3,7 @@ package de.twomartens.timetable.bahnApi.property
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.boot.context.properties.bind.ConstructorBinding
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "de.twomartens.timetable.bahn-api")
|
||||
@Schema(description = "Properties to configure the BahnAPI")
|
||||
data class BahnApiProperties @ConstructorBinding constructor(
|
||||
|
||||
+7
-37
@@ -1,8 +1,5 @@
|
||||
package de.twomartens.timetable.bahnApi.service
|
||||
|
||||
import de.twomartens.support.model.LeadershipStatus
|
||||
import de.twomartens.support.service.BusService
|
||||
import de.twomartens.timetable.bahnApi.events.ScheduledTasksCreatedEvent
|
||||
import de.twomartens.timetable.bahnApi.model.Eva
|
||||
import de.twomartens.timetable.bahnApi.model.FetchDates
|
||||
import de.twomartens.timetable.bahnApi.model.TaskFactory
|
||||
@@ -13,20 +10,15 @@ import de.twomartens.timetable.types.Hour
|
||||
import de.twomartens.timetable.types.HourAtDay
|
||||
import mu.KotlinLogging
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent
|
||||
import org.springframework.cloud.kubernetes.commons.leader.LeaderProperties
|
||||
import org.springframework.context.event.EventListener
|
||||
import org.springframework.data.mongodb.core.BulkOperations
|
||||
import org.springframework.data.mongodb.core.MongoTemplate
|
||||
import org.springframework.integration.leader.event.OnGrantedEvent
|
||||
import org.springframework.stereotype.Service
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
|
||||
@Service
|
||||
class ScheduledTaskService(
|
||||
private val busService: BusService,
|
||||
private val leadershipStatus: LeadershipStatus,
|
||||
private val leaderProperties: LeaderProperties,
|
||||
private val scheduledFetchTaskRepository: ScheduledFetchTaskRepository,
|
||||
private val taskFactory: TaskFactory,
|
||||
private val fetchTaskScheduler: FetchTaskScheduler,
|
||||
@@ -37,30 +29,16 @@ class ScheduledTaskService(
|
||||
|
||||
@EventListener(ApplicationReadyEvent::class)
|
||||
fun onApplicationReady(event: ApplicationReadyEvent) {
|
||||
if (!leaderProperties.isEnabled) {
|
||||
log.info { "Leader election disabled and application ready" }
|
||||
val updateTime = Instant.ofEpochMilli(event.timestamp)
|
||||
updateTaskCounterAndScheduleTasksIfLeader(updateTime)
|
||||
}
|
||||
}
|
||||
|
||||
@EventListener(OnGrantedEvent::class)
|
||||
fun onLeadershipGranted(event: OnGrantedEvent) {
|
||||
log.info { "Granted leadership" }
|
||||
log.info { "Application ready" }
|
||||
val updateTime = Instant.ofEpochMilli(event.timestamp)
|
||||
updateTaskCounterAndScheduleTasksIfLeader(updateTime)
|
||||
updateTaskCounterAndScheduleTasks(updateTime)
|
||||
}
|
||||
|
||||
@EventListener(ScheduledTasksCreatedEvent::class)
|
||||
fun onScheduledTasksCreated(event: ScheduledTasksCreatedEvent) {
|
||||
updateTaskCounterAndScheduleTasksIfLeader(event.source)
|
||||
}
|
||||
|
||||
private fun updateTaskCounterAndScheduleTasksIfLeader(updateTime: Instant) {
|
||||
log.info { "Update tasks from database and schedule if leader" }
|
||||
private fun updateTaskCounterAndScheduleTasks(updateTime: Instant) {
|
||||
log.info { "Update tasks from database and schedule" }
|
||||
val createdTasks = findTasksCreatedSince(lastUpdate)
|
||||
updateCounterIfNotUpToDate(updateTime, createdTasks)
|
||||
scheduleTasksIfLeader(createdTasks)
|
||||
scheduleTasks(createdTasks)
|
||||
lastUpdate = updateTime
|
||||
}
|
||||
|
||||
@@ -72,7 +50,6 @@ class ScheduledTaskService(
|
||||
val newTasks = buildScheduledTasks(tswRoute, fetchDates)
|
||||
|
||||
storeTasksInDatabaseAndStoreCreationTime(newTasks)
|
||||
publishTasksCreatedEvent()
|
||||
}
|
||||
|
||||
private fun calculateDatesToFetch(fetchedDate: LocalDate): FetchDates {
|
||||
@@ -109,10 +86,8 @@ class ScheduledTaskService(
|
||||
return newTasks
|
||||
}
|
||||
|
||||
private fun scheduleTasksIfLeader(tasksToSchedule: List<ScheduledFetchTask>) {
|
||||
if (leadershipStatus.isLeader) {
|
||||
fetchTaskScheduler.scheduleFetchTasks(tasksToSchedule)
|
||||
}
|
||||
private fun scheduleTasks(tasksToSchedule: List<ScheduledFetchTask>) {
|
||||
fetchTaskScheduler.scheduleFetchTasks(tasksToSchedule)
|
||||
}
|
||||
|
||||
private fun updateCounterIfNotUpToDate(updateTime: Instant,
|
||||
@@ -139,11 +114,6 @@ class ScheduledTaskService(
|
||||
.execute()
|
||||
}
|
||||
|
||||
private fun publishTasksCreatedEvent() {
|
||||
val event = ScheduledTasksCreatedEvent.of(createdTime)
|
||||
busService.publishEvent(event)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val log = KotlinLogging.logger {}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,4 @@ dependencies {
|
||||
kapt(libs.mapstruct.processor)
|
||||
|
||||
implementation(libs.bundles.spring.boot.security)
|
||||
implementation(libs.spring.cloud.starter.config)
|
||||
implementation(libs.spring.cloud.leader.election)
|
||||
implementation(libs.spring.cloud.starter.bus.kafka)
|
||||
}
|
||||
|
||||
@@ -1,44 +1,15 @@
|
||||
package de.twomartens.timetable
|
||||
|
||||
import de.twomartens.support.model.LeadershipStatus
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent
|
||||
import org.springframework.boot.runApplication
|
||||
import org.springframework.cloud.kubernetes.commons.leader.LeaderProperties
|
||||
import org.springframework.context.event.EventListener
|
||||
import org.springframework.data.mongodb.config.EnableMongoAuditing
|
||||
import org.springframework.integration.leader.event.OnGrantedEvent
|
||||
import org.springframework.integration.leader.event.OnRevokedEvent
|
||||
import org.springframework.scheduling.annotation.EnableScheduling
|
||||
|
||||
@EnableMongoAuditing
|
||||
@EnableScheduling
|
||||
@SpringBootApplication(scanBasePackages = ["de.twomartens.support", "de.twomartens.timetable"])
|
||||
open class MainApplication(
|
||||
private val leadershipStatus: LeadershipStatus,
|
||||
private val leaderProperties: LeaderProperties
|
||||
) {
|
||||
@EventListener(ApplicationReadyEvent::class)
|
||||
fun ready(event: ApplicationReadyEvent) {
|
||||
setInitialLeadershipStatus()
|
||||
}
|
||||
|
||||
@EventListener(OnGrantedEvent::class)
|
||||
fun onLeadershipGranted(event: OnGrantedEvent) {
|
||||
leadershipStatus.isLeader = true
|
||||
}
|
||||
|
||||
@EventListener(OnRevokedEvent::class)
|
||||
fun onLeadershipRevoked(event: OnRevokedEvent) {
|
||||
leadershipStatus.isLeader = false
|
||||
}
|
||||
|
||||
private fun setInitialLeadershipStatus() {
|
||||
leadershipStatus.isLeader = !leaderProperties.isEnabled
|
||||
}
|
||||
}
|
||||
open class MainApplication() {}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
runApplication<MainApplication>(*args)
|
||||
}
|
||||
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package de.twomartens.timetable.configuration
|
||||
|
||||
import org.springframework.cloud.bus.jackson.RemoteApplicationEventScan
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration
|
||||
@RemoteApplicationEventScan(basePackages = ["de.twomartens.timetable", "de.twomartens.support"])
|
||||
open class BusConfiguration
|
||||
+1
-3
@@ -7,12 +7,10 @@ import de.twomartens.support.property.TimeProperties
|
||||
import de.twomartens.timetable.bahnApi.property.BahnApiProperties
|
||||
import de.twomartens.timetable.property.ServiceProperties
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.cloud.kubernetes.commons.leader.LeaderProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(RestTemplateTimeoutProperties::class, ServiceProperties::class,
|
||||
StatusProbeProperties::class, TimeProperties::class, BahnApiProperties::class,
|
||||
HealthCheckProperties::class,
|
||||
LeaderProperties::class)
|
||||
HealthCheckProperties::class)
|
||||
open class PropertyConfiguration
|
||||
|
||||
@@ -5,11 +5,9 @@ import de.twomartens.timetable.model.common.LanguageCode
|
||||
import de.twomartens.timetable.types.NonEmptyString
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "de.twomartens.timetable")
|
||||
@Schema(description = "Properties, to configure this Application")
|
||||
class ServiceProperties {
|
||||
open class ServiceProperties {
|
||||
lateinit var countryNames: Map<CountryCode, Map<LanguageCode, NonEmptyString>>
|
||||
}
|
||||
|
||||
@@ -1,13 +1,2 @@
|
||||
server.port: 12100
|
||||
management.server.port: 12101
|
||||
|
||||
|
||||
spring:
|
||||
cloud:
|
||||
kubernetes:
|
||||
leader:
|
||||
enabled: false
|
||||
config:
|
||||
import:
|
||||
- "classpath:config/timetable.yaml"
|
||||
- "optional:configserver:${CONFIGSERVER_SCHEME:http}://${CONFIGSERVER_HOST:localhost}:${CONFIGSERVER_PORT:8888}${CONFIGSERVER_PREFIX:/config}"
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
spring:
|
||||
config:
|
||||
import:
|
||||
- "configserver:${CONFIGSERVER_SCHEME:http}://${CONFIGSERVER_HOST:configserver}:${CONFIGSERVER_PORT:8888}${CONFIGSERVER_PREFIX:/config}"
|
||||
kafka:
|
||||
bootstrap-servers:
|
||||
- ${KAFKA_HOST:kafka}:${KAFKA_PORT:9092}
|
||||
|
||||
@@ -26,12 +26,6 @@ management:
|
||||
http.server.requests: true
|
||||
|
||||
spring:
|
||||
cloud:
|
||||
config:
|
||||
name: timetable
|
||||
kubernetes:
|
||||
leader:
|
||||
enabled: true
|
||||
main:
|
||||
banner-mode: off
|
||||
profiles:
|
||||
@@ -84,6 +78,12 @@ de.twomartens.timetable:
|
||||
bahn-api:
|
||||
client-id: ${DB_CLIENT_ID}
|
||||
client-secret: ${DB_CLIENT_SECRET}
|
||||
greeting: "Hello %s, on millenium"
|
||||
statusprobe:
|
||||
scheduleDuration: 60
|
||||
maxKafkaFailureDuration: 5
|
||||
maxBlobFailureCount: 5
|
||||
maxFailurePercent: 50
|
||||
de.twomartens.support.health.greeting: "Good morning"
|
||||
|
||||
time:
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package de.twomartens.support.model
|
||||
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class LeadershipStatus {
|
||||
var isLeader = false
|
||||
}
|
||||
@@ -4,16 +4,13 @@ import io.swagger.v3.oas.annotations.media.Schema
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.boot.context.properties.bind.ConstructorBinding
|
||||
import org.springframework.boot.convert.DurationUnit
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
import java.time.Duration
|
||||
import java.time.temporal.ChronoUnit
|
||||
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "de.twomartens.timetable.statusprobe")
|
||||
@Schema(description = "Properties, to configure this Application")
|
||||
data class StatusProbeProperties @ConstructorBinding constructor(
|
||||
@DurationUnit(ChronoUnit.SECONDS) val scheduleDuration: Duration,
|
||||
@DurationUnit(ChronoUnit.MINUTES) val maxKafkaFailureDuration: Duration,
|
||||
val maxBlobFailureCount: Int,
|
||||
val maxFailurePercent: Int
|
||||
)
|
||||
|
||||
@@ -3,10 +3,8 @@ package de.twomartens.support.property
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.boot.context.properties.bind.ConstructorBinding
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
import java.time.ZoneId
|
||||
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "time")
|
||||
@Schema(description = "Properties to configure time")
|
||||
data class TimeProperties @ConstructorBinding constructor(
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package de.twomartens.support.service
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider
|
||||
import org.springframework.cloud.bus.BusBridge
|
||||
import org.springframework.cloud.bus.event.RemoteApplicationEvent
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Service
|
||||
class BusService(
|
||||
private val busBridge: ObjectProvider<BusBridge>
|
||||
) {
|
||||
fun publishEvent(event: RemoteApplicationEvent) {
|
||||
busBridge.ifAvailable {
|
||||
it.send(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,4 @@ dependencies {
|
||||
implementation(libs.spring.openapi)
|
||||
|
||||
implementation(libs.bundles.spring.boot.security)
|
||||
implementation(libs.spring.cloud.leader.election)
|
||||
implementation(libs.spring.cloud.starter.bus.kafka)
|
||||
}
|
||||
Reference in New Issue
Block a user