migration WIP

rm0193-mapreduce
Thibault Duplessis 2019-12-01 12:03:39 -06:00
parent c27821e881
commit 3d179646eb
11 changed files with 72 additions and 88 deletions

View File

@ -282,7 +282,7 @@ lazy val practice = module("practice", Seq(common, db, memo, user, study)).setti
)
lazy val playban = module("playban", Seq(common, db, game, message, chat)).settings(
libraryDependencies ++= provided(play.api) ++ reactivemongo.bundle
libraryDependencies ++= provided(play.api, play.joda) ++ reactivemongo.bundle
)
lazy val push = module("push", Seq(common, db, user, game, challenge, message)).settings(

View File

@ -3,7 +3,7 @@ package lila.game
// Wrapper around newly created games. We do not know if the id is unique, yet.
case class NewGame(sloppy: Game) extends AnyVal {
def withId(id: Game.ID): Game = sloppy.withId(id)
def withUniqueId(implicit idGenerator: IdGenerator): Fu[Game] =
def withUniqueId(idGenerator: IdGenerator): Fu[Game] =
idGenerator.game dmap sloppy.withId
def start: NewGame = NewGame(sloppy.start)

View File

@ -1,43 +1,27 @@
package lila.playban
import com.typesafe.config.Config
import com.softwaremill.macwire._
import play.api.Configuration
import lila.common.config.CollName
final class Env(
config: Config,
appConfig: Configuration,
messenger: lila.message.MessageApi,
chatApi: lila.chat.ChatApi,
userRepo: lila.user.UserRepo,
lightUser: lila.common.LightUser.Getter,
db: lila.db.Env,
asyncCache: lila.memo.AsyncCache.Builder
) {
private val settings = new {
val CollectionPlayban = config getString "collection.playban"
}
import settings._
private lazy val feedback = new PlaybanFeedback(
chatApi = chatApi,
lightUser = lightUser
private lazy val playbanColl = db(
CollName(appConfig.get[String]("playban.collection.playban"))
)
lazy val api = new PlaybanApi(
coll = db(CollectionPlayban),
sandbag = new SandbagWatch(messenger),
feedback = feedback,
asyncCache = asyncCache,
messenger = messenger
)
}
object Env {
lazy val current: Env = "playban" boot new Env(
config = lila.common.PlayApp loadConfig "playban",
messenger = lila.message.Env.current.api,
chatApi = lila.chat.Env.current.api,
lightUser = lila.user.Env.current.lightUserApi.async,
db = lila.db.Env.current,
asyncCache = lila.memo.Env.current.asyncCache
)
private lazy val feedback = wire[PlaybanFeedback]
private lazy val sandbag = wire[SandbagWatch]
lazy val api = wire[PlaybanApi]
}

View File

@ -5,8 +5,8 @@ import scala.concurrent.duration._
import chess.variant._
import chess.{ Status, Color }
import lila.common.PlayApp.startedSinceMinutes
import lila.common.{ Bus, Iso }
import lila.common.PlayApp.{ startedSinceMinutes, isDev }
import lila.db.dsl._
import lila.game.{ Pov, Game, Player, Source }
import lila.message.{ MessageApi, ModPreset }
@ -18,16 +18,17 @@ final class PlaybanApi(
coll: Coll,
sandbag: SandbagWatch,
feedback: PlaybanFeedback,
userRepo: UserRepo,
asyncCache: lila.memo.AsyncCache.Builder,
messenger: MessageApi
) {
import lila.db.BSON.BSONJodaDateTimeHandler
import reactivemongo.api.bson.Macros
private implicit val OutcomeBSONHandler = new BSONHandler[BSONInteger, Outcome] {
def read(bsonInt: BSONInteger): Outcome = Outcome(bsonInt.value) err s"No such playban outcome: ${bsonInt.value}"
def write(x: Outcome) = BSONInteger(x.id)
}
private implicit val OutcomeBSONHandler = tryHandler[Outcome](
{ case BSONInteger(v) => Outcome(v) toTry s"No such playban outcome: $v" },
x => BSONInteger(x.id)
)
private implicit val RageSitBSONHandler = intIsoHandler(Iso.int[RageSit](RageSit.apply, _.counter))
private implicit val BanBSONHandler = Macros.handler[TempBan]
private implicit val UserRecordBSONHandler = Macros.handler[UserRecord]
@ -39,11 +40,11 @@ final class PlaybanApi(
private def blameable(game: Game): Fu[Boolean] =
(game.source.exists(s => blameableSources(s)) && game.hasClock) ?? {
if (game.rated) fuTrue
else UserRepo.containsEngine(game.userIds) map (!_)
else userRepo.containsEngine(game.userIds) map (!_)
}
private def IfBlameable[A: ornicar.scalalib.Zero](game: Game)(f: => Fu[A]): Fu[A] =
(isDev || startedSinceMinutes(10)) ?? {
startedSinceMinutes(10) ?? {
blameable(game) flatMap { _ ?? f }
}
@ -143,11 +144,11 @@ final class PlaybanApi(
private val cleanUserIds = new lila.memo.ExpireSetMemo(30 minutes)
def currentBan(userId: User.ID): Fu[Option[TempBan]] = !cleanUserIds.get(userId) ?? {
coll.find(
coll.ext.find(
$doc("_id" -> userId, "b.0" $exists true),
$doc("_id" -> false, "b" -> $doc("$slice" -> -1))
).uno[Bdoc].map {
_.flatMap(_.getAs[List[TempBan]]("b")).??(_.find(_.inEffect))
).uno[Bdoc].dmap {
_.flatMap(_.getAsOpt[List[TempBan]]("b")).??(_.find(_.inEffect))
} addEffect { ban =>
if (ban.isEmpty) cleanUserIds put userId
}
@ -166,15 +167,15 @@ final class PlaybanApi(
}
}
def bans(userIds: List[User.ID]): Fu[Map[User.ID, Int]] = coll.find(
def bans(userIds: List[User.ID]): Fu[Map[User.ID, Int]] = coll.ext.find(
$inIds(userIds),
$doc("b" -> true)
).list[Bdoc]().map {
_.flatMap { obj =>
obj.getAs[User.ID]("_id") flatMap { id =>
obj.getAs[Barr]("b") map { id -> _.stream.size }
obj.getAsOpt[User.ID]("_id") flatMap { id =>
obj.getAsOpt[Barr]("b") map { id -> _.size }
}
}(scala.collection.breakOut)
}.toMap
}
def getRageSit(userId: User.ID) = rageSitCache get userId
@ -196,10 +197,10 @@ final class PlaybanApi(
),
fetchNewObject = true,
upsert = true
).map(_.value) map2 UserRecordBSONHandler.read flatten
).dmap(_.value flatMap UserRecordBSONHandler.readOpt) orFail
s"can't find newly created record for user $userId" flatMap { record =>
(outcome != Outcome.Good) ?? {
UserRepo.createdAtById(userId).flatMap { _ ?? { legiferate(record, _) } }
userRepo.createdAtById(userId).flatMap { _ ?? { legiferate(record, _) } }
} >> {
(rageSitDelta != 0) ?? registerRageSit(record, rageSitDelta)
}
@ -213,8 +214,8 @@ final class PlaybanApi(
lila.log("ragesit").warn(s"Close https://lichess.org/@/${record.userId} ragesit=${record.rageSit}")
funit
} else if (record.rageSit.isVeryBad) for {
mod <- UserRepo.lichess
user <- UserRepo byId record.userId
mod <- userRepo.lichess
user <- userRepo byId record.userId
} yield (mod zip user).headOption foreach {
case (m, u) =>
lila.log("ragesit").info(s"https://lichess.org/@/${u.username} ${record.rageSit.counterView}")

View File

@ -8,7 +8,10 @@ import lila.game.Game
import lila.message.{ MessageApi, ModPreset }
import lila.user.{ User, UserRepo }
private final class SandbagWatch(messenger: MessageApi) {
private final class SandbagWatch(
userRepo: UserRepo,
messenger: MessageApi
) {
import SandbagWatch._
@ -23,8 +26,8 @@ private final class SandbagWatch(messenger: MessageApi) {
}
private def sendMessage(userId: User.ID): Funit = for {
mod <- UserRepo.lichess
user <- UserRepo byId userId
mod <- userRepo.lichess
user <- userRepo byId userId
} yield (mod zip user).headOption.?? {
case (m, u) =>
lila.log("sandbag").info(s"https://lichess.org/@/${u.username}")

View File

@ -2,6 +2,7 @@ package lila.playban
import org.joda.time.DateTime
import play.api.libs.json._
import play.api.libs.json.JodaWrites._
import scala.math.{ log10, sqrt }
import lila.game.Game

View File

@ -1,39 +1,32 @@
package lila.pool
import com.softwaremill.macwire._
import scala.concurrent.duration._
import lila.hub.FutureSequencer
import lila.common.Bus
import lila.game.Game
import lila.hub.FutureSequencer
final class Env(
system: akka.actor.ActorSystem,
userRepo: lila.user.UserRepo,
gameRepo: lila.game.GameRepo,
idGenerator: lila.game.IdGenerator,
playbanApi: lila.playban.PlaybanApi
) {
)(implicit system: akka.actor.ActorSystem) {
private lazy val hookThieve = new HookThieve()(system)
private lazy val hookThieve = wire[HookThieve]
lazy val api = new PoolApi(
configs = PoolList.all,
hookThieve = hookThieve,
gameStarter = gameStarter,
playbanApi = playbanApi,
system = system
private lazy val configs = PoolList.all
private lazy val sequencer = new FutureSequencer(
system = system,
executionTimeout = 5.seconds.some,
logger = logger
)
private lazy val gameStarter = new GameStarter(
onStart = gameId => Bus.publish(lila.game.Game.Id(gameId), "gameStartId"),
sequencer = new FutureSequencer(
system = system,
executionTimeout = 5.seconds.some,
logger = logger
)
)
}
object Env {
lazy val current: Env = "pool" boot new Env(
system = lila.common.PlayApp.system,
playbanApi = lila.playban.Env.current.api
)
private val onStart = (gameId: Game.Id) => Bus.publish(gameId, "gameStartId")
private lazy val gameStarter = wire[GameStarter]
lazy val api = wire[PoolApi]
}

View File

@ -3,13 +3,16 @@ package lila.pool
import akka.actor._
import scala.concurrent.Promise
import lila.game.{ Game, Player, GameRepo }
import lila.game.{ Game, Player, GameRepo, IdGenerator }
import lila.hub.FutureSequencer
import lila.rating.Perf
import lila.user.{ User, UserRepo }
private final class GameStarter(
onStart: Game.ID => Unit,
userRepo: UserRepo,
gameRepo: GameRepo,
idGenerator: IdGenerator,
onStart: Game.Id => Unit,
sequencer: FutureSequencer
) {
@ -18,7 +21,7 @@ private final class GameStarter(
def apply(pool: PoolConfig, couples: Vector[MatchMaking.Couple]): Funit = couples.nonEmpty ?? {
sequencer {
val userIds = couples.flatMap(_.userIds)
UserRepo.perfOf(userIds, pool.perfType) flatMap { perfs =>
userRepo.perfOf(userIds, pool.perfType) flatMap { perfs =>
couples.map(one(pool, perfs)).sequenceFu.map { pairings =>
lila.common.Bus.publish(Pairings(pairings.flatten.toList), "poolPairings")
}
@ -30,17 +33,17 @@ private final class GameStarter(
import couple._
(perfs.get(p1.userId) |@| perfs.get(p2.userId)).tupled ?? {
case (perf1, perf2) => for {
p1White <- UserRepo.firstGetsWhite(p1.userId, p2.userId)
p1White <- userRepo.firstGetsWhite(p1.userId, p2.userId)
(whitePerf, blackPerf) = if (p1White) perf1 -> perf2 else perf2 -> perf1
(whiteMember, blackMember) = if (p1White) p1 -> p2 else p2 -> p1
game <- makeGame(
pool,
whiteMember.userId -> whitePerf,
blackMember.userId -> blackPerf
).start.withUniqueId
_ <- GameRepo insertDenormalized game
).start withUniqueId idGenerator
_ <- gameRepo insertDenormalized game
} yield {
onStart(game.id)
onStart(Game.Id(game.id))
Pairing(
game,
whiteSri = whiteMember.sri,

View File

@ -76,7 +76,7 @@ object MatchMaking {
none
},
pairs => Some {
pairs.map { case (a, b) => Couple(a, b) }(scala.collection.breakOut)
pairs.view.map { case (a, b) => Couple(a, b) } to Vector
}
)
}

View File

@ -17,7 +17,7 @@ object PoolList {
PoolConfig(15 ++ 15, Wave(60 seconds, 16 players))
)
val clockStringSet: Set[String] = all.map(_.clock.show)(scala.collection.breakOut)
val clockStringSet: Set[String] = all.view.map(_.clock.show) to Set
private implicit class PimpedInt(self: Int) {
def ++(increment: Int) = chess.Clock.Config(self * 60, increment)

View File

@ -15,7 +15,6 @@ final class ShutupApi(
reporter: akka.actor.ActorSelection
) {
private implicit val doubleListHandler = bsonArrayToListHandler[Double]
private implicit val UserRecordBSONHandler = Macros.handler[UserRecord]
import PublicLine.PublicLineBSONHandler