From d4fad197923f13041ca307176e4fc093dfbaad10 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Fri, 16 Mar 2018 11:06:46 -0500 Subject: [PATCH] get current game from the round proxy when connecting player/watcher --- app/controllers/Round.scala | 39 ++++++++++++++-------- modules/game/src/main/Game.scala | 1 + modules/game/src/main/GameRepo.scala | 6 ++-- modules/round/src/main/Env.scala | 9 +++-- modules/round/src/main/Round.scala | 4 +-- modules/round/src/main/SocketHandler.scala | 12 +++---- 6 files changed, 41 insertions(+), 30 deletions(-) diff --git a/app/controllers/Round.scala b/app/controllers/Round.scala index c7432c0155..42ee2684ba 100644 --- a/app/controllers/Round.scala +++ b/app/controllers/Round.scala @@ -7,7 +7,7 @@ import lila.api.Context import lila.app._ import lila.chat.Chat import lila.common.HTTPRequest -import lila.game.{ Pov, GameRepo, Game => GameModel, PgnDump } +import lila.game.{ Pov, GameRepo, Game => GameModel, PgnDump, PlayerRef } import lila.tournament.{ TourMiniView, Tournament => Tour } import lila.user.{ User => UserModel } import views._ @@ -18,20 +18,23 @@ object Round extends LilaController with TheftPrevention { private def analyser = Env.analyse.analyser def websocketWatcher(gameId: String, color: String) = SocketOption[JsValue] { implicit ctx => - getSocketUid("sri") ?? { uid => - env.socketHandler.watcher( - gameId = gameId, - colorName = color, - uid = uid, - user = ctx.me, - ip = ctx.ip, - userTv = get("userTv") - ) + proxyPov(gameId, color) flatMap { + _ ?? { pov => + getSocketUid("sri") ?? { uid => + env.socketHandler.watcher( + pov = pov, + uid = uid, + user = ctx.me, + ip = ctx.ip, + userTv = get("userTv") + ) map some + } + } } } def websocketPlayer(fullId: String, apiVersion: Int) = SocketEither[JsValue] { implicit ctx => - GameRepo pov fullId flatMap { + proxyPov(fullId) flatMap { case Some(pov) => if (isTheft(pov)) fuccess(Left(theftResponse)) else getSocketUid("sri") match { @@ -84,7 +87,7 @@ object Round extends LilaController with TheftPrevention { ) map NoCache def player(fullId: String) = Open { implicit ctx => - OptionFuResult(GameRepo pov fullId) { pov => + OptionFuResult(proxyPov(fullId)) { pov => env.checkOutoftime(pov.game) renderPlayer(pov) } @@ -129,7 +132,7 @@ object Round extends LilaController with TheftPrevention { } def watcher(gameId: String, color: String) = Open { implicit ctx => - GameRepo.pov(gameId, color) flatMap { + proxyPov(gameId, color) flatMap { case Some(pov) => get("pov") match { case Some(requestedPov) => (pov.player.userId, pov.opponent.userId) match { case (Some(_), Some(opponent)) if opponent == requestedPov => @@ -148,6 +151,16 @@ object Round extends LilaController with TheftPrevention { } } + private def proxyPov(gameId: String, color: String): Fu[Option[Pov]] = chess.Color(color) ?? { c => + env.roundProxyGame(gameId) map2 { (g: GameModel) => g pov c } + } + private def proxyPov(fullId: String): Fu[Option[Pov]] = { + val ref = PlayerRef(fullId) + env.roundProxyGame(ref.gameId) map { + _ flatMap { _ playerIdPov ref.playerId } + } + } + private[controllers] def watch(pov: Pov, userTv: Option[UserModel] = None)(implicit ctx: Context): Fu[Result] = playablePovForReq(pov.game) match { case Some(player) if userTv.isEmpty => renderPlayer(pov withColor player.color) diff --git a/modules/game/src/main/Game.scala b/modules/game/src/main/Game.scala index 8d485fb3a8..97392b824d 100644 --- a/modules/game/src/main/Game.scala +++ b/modules/game/src/main/Game.scala @@ -552,6 +552,7 @@ case class Game( private def playerMaps[A](f: Player => Option[A]): List[A] = players flatMap { f(_) } def pov(c: Color) = Pov(this, c) + def playerIdPov(playerId: String): Option[Pov] = player(playerId) map { Pov(this, _) } def whitePov = pov(White) def blackPov = pov(Black) def playerPov(p: Player) = pov(p.color) diff --git a/modules/game/src/main/GameRepo.scala b/modules/game/src/main/GameRepo.scala index 4a36c5dcd6..24776dae8a 100644 --- a/modules/game/src/main/GameRepo.scala +++ b/modules/game/src/main/GameRepo.scala @@ -55,10 +55,8 @@ object GameRepo { Color(color) ?? (pov(gameId, _)) def pov(playerRef: PlayerRef): Fu[Option[Pov]] = - coll.byId[Game](playerRef.gameId) map { gameOption => - gameOption flatMap { game => - game player playerRef.playerId map { Pov(game, _) } - } + coll.byId[Game](playerRef.gameId) map { + _ flatMap { _ playerIdPov playerRef.playerId } } def pov(fullId: ID): Fu[Option[Pov]] = pov(PlayerRef(fullId)) diff --git a/modules/round/src/main/Env.scala b/modules/round/src/main/Env.scala index c3ce51151a..057eae9cf4 100644 --- a/modules/round/src/main/Env.scala +++ b/modules/round/src/main/Env.scala @@ -42,7 +42,7 @@ final class Env( val PlayerDisconnectTimeout = config duration "player.disconnect.timeout" val PlayerRagequitTimeout = config duration "player.ragequit.timeout" val AnimationDuration = config duration "animation.duration" - val Moretime = config duration "moretime" + val MoretimeDuration = config duration "moretime" val SocketName = config getString "socket.name" val SocketTimeout = config duration "socket.timeout" val NetDomain = config getString "net.domain" @@ -74,7 +74,7 @@ final class Env( forecastApi = forecastApi, socketHub = socketHub, awakeWith = tell(id), - moretimeDuration = Moretime, + moretimeDuration = MoretimeDuration, activeTtl = ActiveTtl ) def tell(id: Game.ID)(msg: Any): Unit = self ! Tell(id, msg) @@ -85,6 +85,9 @@ final class Env( }: Receive) orElse actorMapReceive }), name = ActorMapName) + def roundProxyGame(gameId: String): Fu[Option[Game]] = + roundMap ? Ask(gameId, actorApi.GetGame) mapTo manifest[Option[Game]] + private var nbRounds = 0 def count() = nbRounds @@ -199,7 +202,7 @@ final class Env( divider = divider, evalCache = evalCache, baseAnimationDuration = AnimationDuration, - moretimeSeconds = Moretime.toSeconds.toInt + moretimeSeconds = MoretimeDuration.toSeconds.toInt ) lazy val noteApi = new NoteApi(db(CollectionNote)) diff --git a/modules/round/src/main/Round.scala b/modules/round/src/main/Round.scala index 44aaedeac9..28f6d24f97 100644 --- a/modules/round/src/main/Round.scala +++ b/modules/round/src/main/Round.scala @@ -254,13 +254,13 @@ private[round] final class Round( } private def scheduleExpiration: Funit = proxy.game map { - _ ?? { game => + case None => self ! PoisonPill + case Some(game) => game.timeBeforeExpiration foreach { centis => context.system.scheduler.scheduleOnce((centis.millis + 1000).millis) { awakeWith(NoStart) } } - } } private def handle[A](op: Game => Fu[Events]): Funit = diff --git a/modules/round/src/main/SocketHandler.scala b/modules/round/src/main/SocketHandler.scala index 56927cad56..1264d0d058 100644 --- a/modules/round/src/main/SocketHandler.scala +++ b/modules/round/src/main/SocketHandler.scala @@ -10,8 +10,9 @@ import chess.{ Centis, MoveMetrics, Color } import play.api.libs.json.{ JsObject, Json } import actorApi._, round._ +import lila.chat.Chat import lila.common.IpAddress -import lila.game.{ Pov, PovRef, GameRepo, Game } +import lila.game.{ Pov, PovRef, Game } import lila.hub.actorApi.map._ import lila.hub.actorApi.round.Berserk import lila.hub.actorApi.shutup.PublicSource @@ -19,7 +20,6 @@ import lila.socket.actorApi.{ Connected => _, _ } import lila.socket.Handler import lila.socket.Socket.Uid import lila.user.User -import lila.chat.Chat import makeTimeout.short private[round] final class SocketHandler( @@ -116,16 +116,12 @@ private[round] final class SocketHandler( } def watcher( - gameId: String, - colorName: String, + pov: Pov, uid: Uid, user: Option[User], ip: IpAddress, userTv: Option[String] - ): Fu[Option[JsSocketHandler]] = - GameRepo.pov(gameId, colorName) flatMap { - _ ?? { join(_, none, uid, user, ip, userTv = userTv) map some } - } + ): Fu[JsSocketHandler] = join(pov, none, uid, user, ip, userTv = userTv) def player( pov: Pov,