diff --git a/src/main/kotlin/com/faforever/icebreaker/persistence/IceSessionEntity.kt b/src/main/kotlin/com/faforever/icebreaker/persistence/IceSessionEntity.kt index 35b7273..e0b7dd5 100644 --- a/src/main/kotlin/com/faforever/icebreaker/persistence/IceSessionEntity.kt +++ b/src/main/kotlin/com/faforever/icebreaker/persistence/IceSessionEntity.kt @@ -28,4 +28,17 @@ class IceSessionRepository : PanacheRepository { fun findByCreatedAtLesserThan(instant: Instant) = find("createdAt <= ?1", instant).list() + + fun acquireGameLock(gameId: Long, timeout: Int = 10) { + getEntityManager().createNativeQuery("SELECT GET_LOCK(:lockName,:timeout)", Boolean::class.java).apply { + setParameter("lockName", "game_id_$gameId") + setParameter("timeout", timeout) + }.singleResult + } + + fun releaseGameLock(gameId: Long) { + getEntityManager().createNativeQuery("SELECT RELEASE_LOCK(:lockName)", Boolean::class.java).apply { + setParameter("lockName", "game_id_$gameId") + }.singleResult + } } diff --git a/src/main/kotlin/com/faforever/icebreaker/service/SessionService.kt b/src/main/kotlin/com/faforever/icebreaker/service/SessionService.kt index 286c0b7..88f23c2 100644 --- a/src/main/kotlin/com/faforever/icebreaker/service/SessionService.kt +++ b/src/main/kotlin/com/faforever/icebreaker/service/SessionService.kt @@ -26,21 +26,27 @@ class SessionService( @Transactional fun getSession(gameId: Long): Session { - val session = iceSessionRepository.findByGameId(gameId) - ?: IceSessionEntity(gameId = gameId, createdAt = Instant.now()).also { - LOG.debug("Creating session for gameId $gameId") - iceSessionRepository.persist(it) + try { + iceSessionRepository.acquireGameLock(gameId) + + val session = iceSessionRepository.findByGameId(gameId) + ?: IceSessionEntity(gameId = gameId, createdAt = Instant.now()).also { + LOG.debug("Creating session for gameId $gameId") + iceSessionRepository.persist(it) + } + + val servers = activeSessionHandlers.flatMap { + it.createSession(session.id) + it.getIceServersSession(session.id) } - val servers = activeSessionHandlers.flatMap { - it.createSession(session.id) - it.getIceServersSession(session.id) + return Session( + id = session.id, + servers = servers, + ) + } finally { + iceSessionRepository.releaseGameLock(gameId) } - - return Session( - id = session.id, - servers = servers, - ) } @Transactional