finish abandoned games after 10 days

pull/83/head
Thibault Duplessis 2012-10-08 17:55:10 +02:00
parent 1003f7e14b
commit 49b0403352
9 changed files with 63 additions and 23 deletions

View File

@ -64,6 +64,9 @@ sudo ln -s /path/to/lila/bin/prod/archlinux/conf.d/lila ./
- Configure the daemon in /etc/conf.d/lila
- Add lila to DAEMONS in /etc/rc.conf
Optional
ulimit -n 99999
Restart on timeout
------------------

View File

@ -154,6 +154,7 @@ final class CoreEnv private (application: Application, val settings: Settings) {
lazy val titivate = new lila.core.Titivate(
gameRepo = game.gameRepo,
finisher = round.finisher,
meddler = round.meddler,
bookmarkApi = bookmark.api)
lazy val mod = new lila.mod.ModEnv(

View File

@ -40,11 +40,11 @@ object Cron {
}
}
effect(2 seconds, "fisherman cleanup") {
effect(2 seconds, "fisherman: cleanup") {
env.lobby.fisherman.cleanup
}
effect(10 seconds, "lobby cleanup") {
effect(10 seconds, "lobby: cleanup") {
env.lobby.hookRepo.cleanupOld
}
@ -56,18 +56,23 @@ object Cron {
if (current.mode != Mode.Dev) {
effect(4.1 hours, "game cleanup") {
env.ai.clientDiagnose
effect(4.17 hours, "game: cleanup") {
env.titivate.cleanupUnplayed flatMap { _
env.titivate.cleanupNext
}
}
effect(1 hour, "game finish") {
effect(1.13 hour, "game: finish by clock") {
env.titivate.finishByClock
}
env.ai.clientDiagnose
effect(1 minutes, "game: finish abandoned") {
env.titivate.finishAbandoned
}
}
unsafe(10 seconds, "ai: diagnose") {
env.ai.clientDiagnose
}

View File

@ -2,7 +2,7 @@ package lila
package core
import game.GameRepo
import round.Finisher
import round.{ Finisher, Meddler }
import bookmark.BookmarkApi
import com.mongodb.casbah.query.Imports._
@ -11,18 +11,26 @@ import org.scala_tools.time.Imports._
import scalaz.effects._
final class Titivate(
gameRepo: GameRepo,
finisher: Finisher,
bookmarkApi: BookmarkApi) {
gameRepo: GameRepo,
finisher: Finisher,
meddler: Meddler,
bookmarkApi: BookmarkApi) {
val finishByClock: IO[Unit] =
for {
games gameRepo.candidatesToAutofinish
_ (finisher outoftimes games).sequence
} yield ()
val finishByClock: IO[Unit] = for {
games gameRepo.candidatesToAutofinish
_ putStrLn("[titivate] Finish %d games by clock" format games.size)
_ (finisher outoftimes games).sequence
} yield ()
val cleanupUnplayed = for {
val finishAbandoned: IO[Unit] = for {
games gameRepo abandoned 200
_ putStrLn("[titivate] Finish %d abandoned games" format games.size)
_ (games map meddler.finishAbandoned).sequence
} yield ()
val cleanupUnplayed: IO[Unit] = for {
ids gameRepo.unplayedIds
_ putStrLn("[titivate] Remove %d unplayed games" format ids.size)
_ gameRepo removeIds ids
_ bookmarkApi removeByGameIds ids
} yield ()

View File

@ -333,7 +333,7 @@ case class DbGame(
def pgnList = pgn.split(' ').toList
def playerWhoDidNotMove: Option[DbPlayer] = turns match {
case 0 player(White).some
case 0 player(White).some
case 1 player(Black).some
case _ none
}
@ -356,6 +356,11 @@ case class DbGame(
def isBeingPlayed =
!finishedOrAborted && updatedAt.fold(_ > DateTime.now - 20.seconds, false)
def abandoned = updatedAt.fold(
u (status <= Status.Started) && (u <= DbGame.abandonedDate),
false
)
def hasBookmarks = bookmarks > 0
def showBookmarks = if (hasBookmarks) bookmarks else ""
@ -408,6 +413,8 @@ object DbGame {
val playerIdSize = 4
val fullIdSize = 12
def abandonedDate = DateTime.now - 10.days
def takeGameId(fullId: String) = fullId take gameIdSize
def apply(

View File

@ -133,8 +133,8 @@ final class GameRepo(collection: MongoCollection)
val unplayedIds: IO[List[String]] = io {
primitiveProjections[String](
("turns" $lt 2) ++
("createdAt" $lt (DateTime.now - 2.day) $gt (DateTime.now - 1.month)),
("turns" $lt 2) ++
("createdAt" $lt (DateTime.now - 2.day) $gt (DateTime.now - 1.month)),
"_id"
)
}
@ -148,7 +148,7 @@ final class GameRepo(collection: MongoCollection)
remove("_id" $in ids)
}
def candidatesToAutofinish: IO[List[DbGame]] = io {
val candidatesToAutofinish: IO[List[DbGame]] = io {
find(Query.playable ++
Query.clock(true) ++
("createdAt" $gt (DateTime.now - 1.day)) ++ // index
@ -156,7 +156,13 @@ final class GameRepo(collection: MongoCollection)
).toList.map(_.decode).flatten
}
def featuredCandidates: IO[List[DbGame]] = io {
def abandoned(max: Int): IO[List[DbGame]] = io {
find(
Query.notFinished ++ ("updatedAt" $lt DbGame.abandonedDate)
).limit(max).toList.map(_.decode).flatten
}
val featuredCandidates: IO[List[DbGame]] = io {
find(Query.playable ++
Query.clock(true) ++
("turns" $gt 1) ++
@ -177,7 +183,7 @@ final class GameRepo(collection: MongoCollection)
find(Query.started ++ Query.turnsGt(1))
.sort(Query.sortCreated)
.limit(limit)
.toList.map(_.decode).flatten
.toList.map(_.decode).flatten
}
def games(ids: List[String]): IO[List[DbGame]] = io {

View File

@ -27,7 +27,7 @@ object Query {
val finished: DBObject = "status" $in List(Status.Mate.id, Status.Resign.id, Status.Outoftime.id, Status.Timeout.id)
val notFinished: DBObject = DBObject("status" -> Status.Started.id)
val notFinished: DBObject = "status" $lte Status.Started.id
val frozen: DBObject = "status" $gte Status.Mate.id

View File

@ -36,4 +36,14 @@ final class Meddler(
povOption gameRepo pov povRef
_ povOption.fold(resign, putStrLn("Cannot resign missing game " + povRef))
} yield ()
def finishAbandoned(game: DbGame): IO[Unit] = game.abandoned.fold(
finisher.resign(Pov(game, game.player))
.prefixFailuresWith("Finish abandoned game " + game.id)
.fold(
err putStrLn(err.shows),
_ map (_ ()) // discard the events
),
putStrLn("Game is not abandoned")
)
}

View File

@ -31,7 +31,7 @@ final class Indexer(
def count(request: CountRequest): Int = request.in(indexName, typeName)(es)
val indexQueue: IO[Unit] = for {
ids queue next 1000
ids queue next 2000
_ ids.toNel.fold(
neIds for {
_ putStrLn("Search indexing %d games" format neIds.list.size)