Added tasks for async fetching and storing timetables

This commit is contained in:
2023-10-02 23:03:02 +02:00
parent d3a8e0abc8
commit d1b681bfad
10 changed files with 158 additions and 9 deletions
@@ -1,6 +1,7 @@
package de.twomartens.timetable
import de.twomartens.timetable.bahnApi.service.BahnApiService
import de.twomartens.timetable.bahnApi.service.BahnDatabaseService
import mu.KotlinLogging
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.event.ApplicationReadyEvent
@@ -16,16 +17,15 @@ import java.time.Month
@EnableScheduling
@SpringBootApplication
open class MainApplication(
private val bahnApiService: BahnApiService
private val bahnApiService: BahnApiService,
private val bahnDatabaseService: BahnDatabaseService
) {
@EventListener(ApplicationReadyEvent::class)
fun ready() {
val result = bahnApiService.fetchStations("Köln Hbf")
val koeln = result[0]
val timetable = bahnApiService.fetchTimetable(koeln.eva,
LocalDate.of(2023, Month.SEPTEMBER, 23),
LocalTime.of(17, 0))
log.info("stations: $result")
val timetable = bahnApiService.fetchTimetable(8000207,
LocalDate.of(2023, Month.OCTOBER, 1),
LocalTime.of(3, 0))
log.info { "bs" }
}
companion object {
@@ -0,0 +1,25 @@
package de.twomartens.timetable.bahnApi.mapper
import de.twomartens.timetable.bahnApi.model.db.BahnTimetable
import org.mapstruct.*
import java.time.LocalDateTime
@Mapper(
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS,
unmappedTargetPolicy = ReportingPolicy.IGNORE
)
interface BahnTimetableMapper {
@Mapping(target = "id", ignore = true)
@Mapping(target = "created", ignore = true)
@Mapping(target = "lastModified", ignore = true)
fun mapToDB(dto: de.twomartens.timetable.bahnApi.model.dto.BahnTimetable,
dateTime: LocalDateTime): BahnTimetable {
return BahnTimetable(
dto.eva!!,
dateTime,
dto.station,
dto.stops
)
}
}
@@ -0,0 +1,30 @@
package de.twomartens.timetable.bahnApi.model.db
import de.twomartens.timetable.bahnApi.model.dto.BahnStationStop
import org.bson.types.ObjectId
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.Id
import org.springframework.data.annotation.LastModifiedDate
import org.springframework.data.mongodb.core.index.CompoundIndex
import org.springframework.data.mongodb.core.index.TextIndexed
import org.springframework.data.mongodb.core.mapping.Document
import java.time.Instant
import java.time.LocalDateTime
@Document
@CompoundIndex(def = "{'eva': 1, 'dateTime': 1}")
data class BahnTimetable(
var eva: Int,
var dateTime: LocalDateTime,
@TextIndexed var station: String,
var stops: List<BahnStationStop>
) {
@Id
var id: ObjectId = ObjectId()
@CreatedDate
lateinit var created: Instant
@LastModifiedDate
lateinit var lastModified: Instant
}
@@ -0,0 +1,7 @@
package de.twomartens.timetable.bahnApi.repository
import de.twomartens.timetable.bahnApi.model.db.BahnStation
import de.twomartens.timetable.bahnApi.model.db.BahnTimetable
import org.springframework.data.mongodb.repository.MongoRepository
interface BahnTimetableRepository : MongoRepository<BahnTimetable, String>
@@ -31,7 +31,7 @@ class BahnApiService(
return body?.stations ?: listOf()
}
fun fetchTimetable(eva: String, date: LocalDate, hour: LocalTime): BahnTimetable {
fun fetchTimetable(eva: Int, date: LocalDate, hour: LocalTime): BahnTimetable {
val requestEntity = buildRequestEntity<BahnTimetable>()
val dateFormatter = DateTimeFormatter.ofPattern("yyMMdd")
val timeFormatter = DateTimeFormatter.ofPattern("HH")
@@ -1,19 +1,29 @@
package de.twomartens.timetable.bahnApi.service
import de.twomartens.timetable.bahnApi.mapper.BahnStationMapper
import de.twomartens.timetable.bahnApi.mapper.BahnTimetableMapper
import de.twomartens.timetable.bahnApi.model.dto.BahnStation
import de.twomartens.timetable.bahnApi.model.dto.BahnTimetable
import de.twomartens.timetable.bahnApi.repository.BahnStationRepository
import de.twomartens.timetable.bahnApi.repository.BahnTimetableRepository
import org.mapstruct.factory.Mappers
import org.springframework.stereotype.Service
import java.time.LocalDateTime
@Service
class BahnDatabaseService(
private val bahnStationRepository: BahnStationRepository
private val bahnStationRepository: BahnStationRepository,
private val bahnTimetableRepository: BahnTimetableRepository
) {
private val bahnStationMapper = Mappers.getMapper(BahnStationMapper::class.java)
private val bahnTimetableMapper = Mappers.getMapper(BahnTimetableMapper::class.java)
fun storeStations(stations: List<BahnStation>) {
bahnStationRepository.saveAll(stations
.map { bahnStationMapper.mapToDB(it) })
}
fun storeTimetable(timetable: BahnTimetable, dateTime: LocalDateTime) {
bahnTimetableRepository.save(bahnTimetableMapper.mapToDB(timetable, dateTime))
}
}
@@ -0,0 +1,23 @@
package de.twomartens.timetable.bahnApi.tasks
import de.twomartens.timetable.bahnApi.service.BahnApiService
import de.twomartens.timetable.bahnApi.service.BahnDatabaseService
import org.springframework.scheduling.annotation.Async
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
import java.time.LocalDate
import java.time.LocalTime
@Async
open class FetchTimetableTask(
private val eva: Int,
private val date: LocalDate,
private val hour: LocalTime,
private val bahnApiService: BahnApiService,
private val bahnDatabaseService: BahnDatabaseService,
private val executor: ThreadPoolTaskExecutor) : Runnable {
override fun run() {
val timetable = bahnApiService.fetchTimetable(eva, date, hour)
val storeTask = StoreTimetableTask(timetable, date.atTime(hour), bahnDatabaseService)
executor.execute(storeTask)
}
}
@@ -0,0 +1,17 @@
package de.twomartens.timetable.bahnApi.tasks
import de.twomartens.timetable.bahnApi.model.dto.BahnTimetable
import de.twomartens.timetable.bahnApi.service.BahnDatabaseService
import org.springframework.scheduling.annotation.Async
import java.time.LocalDateTime
@Async
open class StoreTimetableTask(
private val timetable: BahnTimetable,
private val dateTime: LocalDateTime,
private val bahnDatabaseService: BahnDatabaseService
) : Runnable {
override fun run() {
bahnDatabaseService.storeTimetable(timetable, dateTime)
}
}
@@ -0,0 +1,17 @@
package de.twomartens.timetable.configuration
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
private const val CORE_POOL_SIZE = 1
@Configuration
open class ThreadPoolTaskExecutorConfig {
@Bean
open fun threadPoolTaskExecutor(): ThreadPoolTaskExecutor {
val executor = ThreadPoolTaskExecutor()
executor.corePoolSize = CORE_POOL_SIZE
return executor
}
}
@@ -0,0 +1,20 @@
package de.twomartens.timetable.configuration
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
private const val POOL_SIZE = 5
private const val THREAD_NAME_PREFIX = "ThreadPoolTaskScheduler"
@Configuration
open class ThreadPoolTaskSchedulerConfig {
@Bean
open fun threadPoolTaskScheduler(): ThreadPoolTaskScheduler {
val scheduler = ThreadPoolTaskScheduler()
scheduler.poolSize = POOL_SIZE
scheduler.threadNamePrefix = THREAD_NAME_PREFIX
return scheduler
}
}