use a FixedThreadPool to execute the timetable updates
continuous-integration/drone/push Build is passing Details

closes #9
This commit is contained in:
Jannik 2019-10-27 13:51:08 +01:00
parent db57059727
commit 3177be1bf0
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
4 changed files with 34 additions and 35 deletions

View File

@ -33,7 +33,7 @@ repositories {
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.1" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2"
implementation 'org.jsoup:jsoup:1.12.1' implementation 'org.jsoup:jsoup:1.12.1'
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'

View File

@ -39,7 +39,6 @@ import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController import org.springframework.web.bind.annotation.RestController
import java.time.LocalDateTime import java.time.LocalDateTime
import java.util.* import java.util.*
import kotlin.collections.ArrayList
@RestController @RestController
class APIController { class APIController {

View File

@ -33,7 +33,9 @@ import org.mosad.thecitadelofricks.hsoparser.TimetableParser
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.util.* import java.util.*
import java.util.concurrent.Executors
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.HashSet
import kotlin.concurrent.scheduleAtFixedRate import kotlin.concurrent.scheduleAtFixedRate
class CacheController { class CacheController {
@ -153,12 +155,8 @@ class CacheController {
*/ */
private fun asyncUpdateCourseList() = GlobalScope.launch { private fun asyncUpdateCourseList() = GlobalScope.launch {
CourseListParser().getCourseLinks(courseListURL)?.let { CourseListParser().getCourseLinks(courseListURL)?.let {
courseList = courseList = CourseList(
CourseList( CourseMeta(System.currentTimeMillis() / 1000, it.size), it
CourseMeta(
System.currentTimeMillis() / 1000,
it.size
), it
) )
} }
@ -175,13 +173,9 @@ class CacheController {
// only update if we get valid data // only update if we get valid data
if (mensaCurrentWeek != null && mensaNextWeek != null) { if (mensaCurrentWeek != null && mensaNextWeek != null) {
mensaMenu = mensaMenu = MensaMenu(
MensaMenu( MensaMeta(System.currentTimeMillis() / 1000, mensaName), mensaCurrentWeek, mensaNextWeek
MensaMeta( )
System.currentTimeMillis() / 1000,
mensaName
), mensaCurrentWeek, mensaNextWeek
)
} }
logger.info("updated mensamenu successful at ${Date(mensaMenu.meta.updateTime * 1000)}") logger.info("updated mensamenu successful at ${Date(mensaMenu.meta.updateTime * 1000)}")
@ -190,14 +184,27 @@ class CacheController {
/** /**
* this function updates all existing timetables * this function updates all existing timetables
* during the update process the old data will be returned for a API request * during the update process the old data will be returned for a API request
* a FixedThreadPool is used to make parallel requests for faster updates
*/ */
private fun asyncUpdateTimetables() = GlobalScope.launch { private fun asyncUpdateTimetables() = GlobalScope.launch {
timetableList.forEach { timetableCourse -> logger.info("updating ${timetableList.size} timetables ...")
val updateURL = timetableCourse.meta.link
timetableCourse.timetable = TimetableParser().getTimeTable(updateURL) // create a new ThreadPool with 5 threads
timetableCourse.meta.updateTime = System.currentTimeMillis() / 1000 val executor = Executors.newFixedThreadPool(5)
try {
timetableList.forEach { timetableCourse ->
executor.execute {
timetableCourse.timetable = TimetableParser().getTimeTable(timetableCourse.meta.link)
timetableCourse.meta.updateTime = System.currentTimeMillis() / 1000
}
}
} catch (ex: Exception) {
logger.error("error while updating the timetables", ex)
} finally {
executor.shutdown()
} }
logger.info("updated ${timetableList.size} timetables successful!")
} }
/** /**
@ -208,13 +215,9 @@ class CacheController {
// get all courses on startup // get all courses on startup
val jobCourseUpdate = GlobalScope.async { val jobCourseUpdate = GlobalScope.async {
CourseListParser().getCourseLinks(courseListURL)?.let { CourseListParser().getCourseLinks(courseListURL)?.let {
courseList = courseList = CourseList(
CourseList( CourseMeta(System.currentTimeMillis() / 1000, it.size), it
CourseMeta( )
System.currentTimeMillis() / 1000,
it.size
), it
)
} }
} }
@ -225,13 +228,9 @@ class CacheController {
// only update if we get valid data // only update if we get valid data
if (mensaCurrentWeek != null && mensaNextWeek != null) { if (mensaCurrentWeek != null && mensaNextWeek != null) {
mensaMenu = mensaMenu = MensaMenu(
MensaMenu( MensaMeta(System.currentTimeMillis() / 1000, mensaName), mensaCurrentWeek, mensaNextWeek
MensaMeta( )
System.currentTimeMillis() / 1000,
mensaName
), mensaCurrentWeek, mensaNextWeek
)
} }
} }

View File

@ -59,7 +59,8 @@ class StatusController {
when (timetableRequests.stream().filter { x -> x.courseName == courseName }.findAny().orElse(null)) { when (timetableRequests.stream().filter { x -> x.courseName == courseName }.findAny().orElse(null)) {
null -> timetableRequests.add(TimetableCounter(courseName, 0)) null -> timetableRequests.add(TimetableCounter(courseName, 0))
} }
timetableRequests.stream().filter { x ->x.courseName == courseName }.findFirst().ifPresent { x -> x.requests++ } timetableRequests.stream().filter { x -> x.courseName == courseName }.findFirst()
.ifPresent { x -> x.requests++ }
// TODO Java 11 // TODO Java 11
// timetableRequests.stream().filter { it.courseName == courseName }.findFirst().ifPresentOrElse({ // timetableRequests.stream().filter { it.courseName == courseName }.findFirst().ifPresentOrElse({