finish abandoned games after 10 days
This commit is contained in:
parent
1003f7e14b
commit
49b0403352
|
@ -64,6 +64,9 @@ sudo ln -s /path/to/lila/bin/prod/archlinux/conf.d/lila ./
|
||||||
- Configure the daemon in /etc/conf.d/lila
|
- Configure the daemon in /etc/conf.d/lila
|
||||||
- Add lila to DAEMONS in /etc/rc.conf
|
- Add lila to DAEMONS in /etc/rc.conf
|
||||||
|
|
||||||
|
Optional
|
||||||
|
ulimit -n 99999
|
||||||
|
|
||||||
Restart on timeout
|
Restart on timeout
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,7 @@ final class CoreEnv private (application: Application, val settings: Settings) {
|
||||||
lazy val titivate = new lila.core.Titivate(
|
lazy val titivate = new lila.core.Titivate(
|
||||||
gameRepo = game.gameRepo,
|
gameRepo = game.gameRepo,
|
||||||
finisher = round.finisher,
|
finisher = round.finisher,
|
||||||
|
meddler = round.meddler,
|
||||||
bookmarkApi = bookmark.api)
|
bookmarkApi = bookmark.api)
|
||||||
|
|
||||||
lazy val mod = new lila.mod.ModEnv(
|
lazy val mod = new lila.mod.ModEnv(
|
||||||
|
|
|
@ -40,11 +40,11 @@ object Cron {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
effect(2 seconds, "fisherman cleanup") {
|
effect(2 seconds, "fisherman: cleanup") {
|
||||||
env.lobby.fisherman.cleanup
|
env.lobby.fisherman.cleanup
|
||||||
}
|
}
|
||||||
|
|
||||||
effect(10 seconds, "lobby cleanup") {
|
effect(10 seconds, "lobby: cleanup") {
|
||||||
env.lobby.hookRepo.cleanupOld
|
env.lobby.hookRepo.cleanupOld
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,18 +56,23 @@ object Cron {
|
||||||
|
|
||||||
if (current.mode != Mode.Dev) {
|
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.cleanupUnplayed flatMap { _ ⇒
|
||||||
env.titivate.cleanupNext
|
env.titivate.cleanupNext
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
effect(1 hour, "game finish") {
|
effect(1.13 hour, "game: finish by clock") {
|
||||||
env.titivate.finishByClock
|
env.titivate.finishByClock
|
||||||
}
|
}
|
||||||
|
|
||||||
env.ai.clientDiagnose
|
effect(1 minutes, "game: finish abandoned") {
|
||||||
|
env.titivate.finishAbandoned
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe(10 seconds, "ai: diagnose") {
|
unsafe(10 seconds, "ai: diagnose") {
|
||||||
env.ai.clientDiagnose
|
env.ai.clientDiagnose
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package lila
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import game.GameRepo
|
import game.GameRepo
|
||||||
import round.Finisher
|
import round.{ Finisher, Meddler }
|
||||||
import bookmark.BookmarkApi
|
import bookmark.BookmarkApi
|
||||||
|
|
||||||
import com.mongodb.casbah.query.Imports._
|
import com.mongodb.casbah.query.Imports._
|
||||||
|
@ -13,16 +13,24 @@ import scalaz.effects._
|
||||||
final class Titivate(
|
final class Titivate(
|
||||||
gameRepo: GameRepo,
|
gameRepo: GameRepo,
|
||||||
finisher: Finisher,
|
finisher: Finisher,
|
||||||
|
meddler: Meddler,
|
||||||
bookmarkApi: BookmarkApi) {
|
bookmarkApi: BookmarkApi) {
|
||||||
|
|
||||||
val finishByClock: IO[Unit] =
|
val finishByClock: IO[Unit] = for {
|
||||||
for {
|
|
||||||
games ← gameRepo.candidatesToAutofinish
|
games ← gameRepo.candidatesToAutofinish
|
||||||
|
_ ← putStrLn("[titivate] Finish %d games by clock" format games.size)
|
||||||
_ ← (finisher outoftimes games).sequence
|
_ ← (finisher outoftimes games).sequence
|
||||||
} yield ()
|
} 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
|
ids ← gameRepo.unplayedIds
|
||||||
|
_ ← putStrLn("[titivate] Remove %d unplayed games" format ids.size)
|
||||||
_ ← gameRepo removeIds ids
|
_ ← gameRepo removeIds ids
|
||||||
_ ← bookmarkApi removeByGameIds ids
|
_ ← bookmarkApi removeByGameIds ids
|
||||||
} yield ()
|
} yield ()
|
||||||
|
|
|
@ -356,6 +356,11 @@ case class DbGame(
|
||||||
def isBeingPlayed =
|
def isBeingPlayed =
|
||||||
!finishedOrAborted && updatedAt.fold(_ > DateTime.now - 20.seconds, false)
|
!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 hasBookmarks = bookmarks > 0
|
||||||
|
|
||||||
def showBookmarks = if (hasBookmarks) bookmarks else ""
|
def showBookmarks = if (hasBookmarks) bookmarks else ""
|
||||||
|
@ -408,6 +413,8 @@ object DbGame {
|
||||||
val playerIdSize = 4
|
val playerIdSize = 4
|
||||||
val fullIdSize = 12
|
val fullIdSize = 12
|
||||||
|
|
||||||
|
def abandonedDate = DateTime.now - 10.days
|
||||||
|
|
||||||
def takeGameId(fullId: String) = fullId take gameIdSize
|
def takeGameId(fullId: String) = fullId take gameIdSize
|
||||||
|
|
||||||
def apply(
|
def apply(
|
||||||
|
|
|
@ -148,7 +148,7 @@ final class GameRepo(collection: MongoCollection)
|
||||||
remove("_id" $in ids)
|
remove("_id" $in ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
def candidatesToAutofinish: IO[List[DbGame]] = io {
|
val candidatesToAutofinish: IO[List[DbGame]] = io {
|
||||||
find(Query.playable ++
|
find(Query.playable ++
|
||||||
Query.clock(true) ++
|
Query.clock(true) ++
|
||||||
("createdAt" $gt (DateTime.now - 1.day)) ++ // index
|
("createdAt" $gt (DateTime.now - 1.day)) ++ // index
|
||||||
|
@ -156,7 +156,13 @@ final class GameRepo(collection: MongoCollection)
|
||||||
).toList.map(_.decode).flatten
|
).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 ++
|
find(Query.playable ++
|
||||||
Query.clock(true) ++
|
Query.clock(true) ++
|
||||||
("turns" $gt 1) ++
|
("turns" $gt 1) ++
|
||||||
|
|
|
@ -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 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
|
val frozen: DBObject = "status" $gte Status.Mate.id
|
||||||
|
|
||||||
|
|
|
@ -36,4 +36,14 @@ final class Meddler(
|
||||||
povOption ← gameRepo pov povRef
|
povOption ← gameRepo pov povRef
|
||||||
_ ← povOption.fold(resign, putStrLn("Cannot resign missing game " + povRef))
|
_ ← povOption.fold(resign, putStrLn("Cannot resign missing game " + povRef))
|
||||||
} yield ()
|
} 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")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ final class Indexer(
|
||||||
def count(request: CountRequest): Int = request.in(indexName, typeName)(es)
|
def count(request: CountRequest): Int = request.in(indexName, typeName)(es)
|
||||||
|
|
||||||
val indexQueue: IO[Unit] = for {
|
val indexQueue: IO[Unit] = for {
|
||||||
ids ← queue next 1000
|
ids ← queue next 2000
|
||||||
_ ← ids.toNel.fold(
|
_ ← ids.toNel.fold(
|
||||||
neIds ⇒ for {
|
neIds ⇒ for {
|
||||||
_ ← putStrLn("Search indexing %d games" format neIds.list.size)
|
_ ← putStrLn("Search indexing %d games" format neIds.list.size)
|
||||||
|
|
Loading…
Reference in a new issue