Skip to content

Commit

Permalink
Add scheduled session cleanup + error logging
Browse files Browse the repository at this point in the history
  • Loading branch information
Brutus5000 committed Oct 28, 2023
1 parent 1b822e3 commit c85541b
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 20 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ val quarkusPlatformVersion: String by project
dependencies {
implementation(enforcedPlatform("$quarkusPlatformGroupId:$quarkusPlatformArtifactId:$quarkusPlatformVersion"))
implementation("io.quarkus:quarkus-config-yaml")
implementation("io.quarkus:quarkus-scheduler")
implementation("io.quarkus:quarkus-resteasy-reactive-jackson")
implementation("io.quarkus:quarkus-container-image-docker")
implementation("io.quarkus:quarkus-hibernate-orm-panache-kotlin")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ interface FafProperties {
fun environment(): String

fun tokenLifetimeSeconds(): Long

fun maxSessionLifeTimeHours(): Long
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import jakarta.inject.Singleton
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.Table
import java.time.LocalDateTime
import java.time.Instant
import java.util.UUID

@Entity
Expand All @@ -17,12 +17,15 @@ data class IceSessionEntity(

val gameId: Long,

val createdAt: LocalDateTime,
val createdAt: Instant,

) : PanacheEntityBase

@Singleton
class IceSessionRepository : PanacheRepository<IceSessionEntity> {
fun findByGameId(gameId: Long) =
find("gameId = ?1", gameId).firstResult()

fun findByCreatedAtLesserThan(instant: Instant) =
find("createdAt <= ?1", instant).list()
}
26 changes: 24 additions & 2 deletions src/main/kotlin/com/faforever/icebreaker/service/SessionService.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
package com.faforever.icebreaker.service

import com.faforever.icebreaker.config.FafProperties
import com.faforever.icebreaker.persistence.IceSessionEntity
import com.faforever.icebreaker.persistence.IceSessionRepository
import io.quarkus.scheduler.Scheduled
import jakarta.enterprise.inject.Instance
import jakarta.inject.Singleton
import jakarta.transaction.Transactional
import java.time.LocalDateTime
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.time.Instant
import java.time.temporal.ChronoUnit

private val LOG: Logger = LoggerFactory.getLogger(SessionService::class.java)

@Singleton
class SessionService(
sessionHandlers: Instance<SessionHandler>,
private val fafProperties: FafProperties,
private val iceSessionRepository: IceSessionRepository,
) {
private val activeSessionHandlers = sessionHandlers.filter { it.active }

@Transactional
fun getSession(gameId: Long): Session {
val session = iceSessionRepository.findByGameId(gameId)
?: IceSessionEntity(gameId = gameId, createdAt = LocalDateTime.now()).also {
?: IceSessionEntity(gameId = gameId, createdAt = Instant.now()).also {
LOG.debug("Creating session for gameId $gameId")
iceSessionRepository.persist(it)
}

Expand All @@ -31,4 +40,17 @@ class SessionService(
servers = servers,
)
}

@Transactional
@Scheduled(every = "10m")
fun cleanUpSessions() {
LOG.info("Cleaning up outdated sessions")
iceSessionRepository.findByCreatedAtLesserThan(
instant = Instant.now().plus(fafProperties.maxSessionLifeTimeHours(), ChronoUnit.HOURS),
).forEach { iceSession ->
LOG.debug("Cleaning up session id ${iceSession.id}")
activeSessionHandlers.forEach { it.deleteSession(iceSession.id) }
iceSessionRepository.delete(iceSession)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import com.faforever.icebreaker.service.Session
import com.faforever.icebreaker.service.SessionHandler
import jakarta.inject.Singleton
import org.eclipse.microprofile.rest.client.RestClientBuilder
import java.io.IOException
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.net.URI

private val LOG: Logger = LoggerFactory.getLogger(XirsysSessionHandler::class.java)

@Singleton
class XirsysSessionHandler(
private val fafProperties: FafProperties,
Expand All @@ -26,7 +29,12 @@ class XirsysSessionHandler(
override val active = xirsysProperties.enabled()

override fun createSession(id: String) {
if (listSessions().contains(id)) return
if (listSessions().contains(id)) {
LOG.debug("Session id $id already exists")
return
}

LOG.debug("Creating session id $id")

val result = xirsysClient.createChannel(
namespace = xirsysProperties.channelNamespace(),
Expand All @@ -35,7 +43,7 @@ class XirsysSessionHandler(
)

if (result is XirsysResponse.Error) {
throw IOException(result.code)
LOG.error("Creating session failed: ${result.code}")
}
}

Expand All @@ -47,18 +55,21 @@ class XirsysSessionHandler(
)

if (result is XirsysResponse.Error) {
throw IOException(result.code)
LOG.error("Deleting session failed: ${result.code}")
}
}

fun listSessions(): List<String> =
private fun listSessions(): List<String> =
when (
val result = xirsysClient.listChannel(
namespace = xirsysProperties.channelNamespace(),
environment = fafProperties.environment(),
)
) {
is XirsysResponse.Error -> throw IOException(result.code)
is XirsysResponse.Error -> emptyList<String>().also {
LOG.error("Listing sessions failed: ${result.code}")
}

is XirsysResponse.Success -> result.data
}

Expand All @@ -71,13 +82,18 @@ class XirsysSessionHandler(
turnRequest = TurnRequest(),
)
) {
is XirsysResponse.Error -> throw IOException(result.code)
is XirsysResponse.Error -> emptyList<Session.Server>().also {
LOG.error("Requesting ICE servers failed: ${result.code}")
}

is XirsysResponse.Success -> result.data.iceServers.let {
Session.Server(
userName = it.username,
secret = it.credential,
iceServerUrls = it.urls,
listOf(
Session.Server(
userName = it.username,
secret = it.credential,
iceServerUrls = it.urls,
),
)
}
}.let { listOf(it) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.faforever.icebreaker.web

import com.faforever.icebreaker.service.Session
import com.faforever.icebreaker.service.SessionService
import io.quarkus.security.PermissionsAllowed
import jakarta.inject.Singleton
import jakarta.ws.rs.GET
import jakarta.ws.rs.Path
Expand All @@ -11,9 +12,9 @@ import org.jboss.resteasy.reactive.RestPath
@Singleton
class SessionController(private val sessionService: SessionService) {

// @PermissionsAllowed("USER:lobby")
@GET
@Path("/game/{gameId}")
@PermissionsAllowed("USER:lobby")
fun getSession(@RestPath gameId: Long): Session =
sessionService.getSession(gameId)
}
11 changes: 8 additions & 3 deletions src/main/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
quarkus:
log:
level: INFO
# category:
# "org.flyway":
# level: DEBUG
application:
name: faf-icebreaker
datasource:
Expand All @@ -27,9 +24,17 @@ mp:
faf:
environment: ${ENVIRONMENT:dev}
token-lifetime-seconds: 30
max-session-life-time-hours: 24
xirsys:
enabled: ${XIRSYS_ENABLED:true}
base-url: "https://global.xirsys.net"
ident: ${XIRSYS_IDENT}
secret: ${XIRSYS_SECRET}
channel-namespace: "faf"

"%dev":
quarkus:
log:
category:
"org.hibernate.SQL":
level: DEBUG
16 changes: 16 additions & 0 deletions src/main/resources/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<withJansi>true</withJansi>
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%cyan(%d{HH:mm:ss.SSS}) %highlight(%-5level) [%-16X{traceId:-no trace}] %gray([%thread]) %magenta(%logger{36})- %msg%n
</pattern>
</encoder>
</appender>

<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

0 comments on commit c85541b

Please sign in to comment.