more IO -> Future

This commit is contained in:
Thibault Duplessis 2012-07-10 01:51:50 +02:00
parent 8c2472dd80
commit 67d0a257c5
3 changed files with 37 additions and 28 deletions

View file

@ -2,12 +2,13 @@ package lila
package ai
import scalaz.effects._
import akka.dispatch.Future
trait Client extends Ai {
val playUrl: String
protected def tryPing: Option[Int]
protected def tryPing: Future[Int]
// tells whether the remote AI is healthy or not
// frequently updated by a scheduled actor
@ -17,13 +18,25 @@ trait Client extends Ai {
def or(fallback: Ai) = if (currentHealth) this else fallback
def currentPing = ping
def currentHealth = ping.fold(_ < pingAlert, false)
def currentHealth = isHealthy(ping)
val diagnose: IO[Unit] = for {
p io(tryPing)
_ p.fold(_ < pingAlert, false).fold(
currentHealth.fold(io(), putStrLn("remote AI is up, ping = " + p)),
putStrLn("remote AI is down, ping = " + p))
_ io { ping = p }
} yield ()
def diagnose: Unit = tryPing onComplete {
case Left(e) {
println("remote AI error: " + e.getMessage)
changePing(none)
}
case Right(p) changePing(p.some)
}
private def changePing(p: Option[Int]) = {
if (isHealthy(p) && !currentHealth)
println("remote AI is up, ping = " + p)
else if (!isHealthy(p) && currentHealth)
println("remote AI is down, ping = " + p)
ping = p
}
private def isHealthy(p: Option[Int]) = p.fold(isFast, false)
private def isFast(p: Int) = p < pingAlert
}

View file

@ -8,7 +8,7 @@ import game.DbGame
import analyse.Analysis
import scalaz.effects._
import akka.dispatch.{ Future, Await }
import akka.dispatch.Future
import akka.util.duration._
import play.api.Play.current
import play.api.libs.concurrent._
@ -31,27 +31,24 @@ final class Client(
case e !![Analysis](e.getMessage)
}
protected lazy val tryPing: Option[Int] = nowMillis |> { start
(unsafe {
Await.result(fetchMove(pgn = "", initialFen = "", level = 1), 5 seconds)
}).toOption flatMap {
case move if UciMove(move).isDefined Some(nowMillis - start) map (_.toInt)
case _ None
protected lazy val tryPing: Future[Int] = nowMillis |> { start
fetchMove(pgn = "", initialFen = "", level = 1) map {
case move if UciMove(move).isDefined (nowMillis - start).toInt
}
}
private def fetchMove(pgn: String, initialFen: String, level: Int): Future[String] =
toAkkaFuture(WS.url(playUrl).post(Map(
"pgn" -> Seq(pgn),
"initialFen" -> Seq(initialFen),
"level" -> Seq(level.toString)
)) map (_.body))
toAkkaFuture(WS.url(playUrl).withQueryString(
"pgn" -> pgn,
"initialFen" -> initialFen,
"level" -> level.toString
).get() map (_.body))
private def fetchAnalyse(pgn: String, initialFen: String): Future[String] =
toAkkaFuture(WS.url(analyseUrl).post(Map(
"pgn" -> Seq(pgn),
"initialFen" -> Seq(initialFen)
)) map (_.body))
toAkkaFuture(WS.url(analyseUrl).withQueryString(
"pgn" -> pgn,
"initialFen" -> initialFen
).get() map (_.body))
private implicit val executor = Akka.system.dispatcher

View file

@ -68,9 +68,9 @@ object Cron {
env.titivate.finishByClock
}
env.ai.clientDiagnose.unsafePerformIO
env.ai.clientDiagnose
}
effect(2 seconds, "ai diagnose") {
unsafe(10 seconds) {
env.ai.clientDiagnose
}
@ -80,7 +80,6 @@ object Cron {
def effect(freq: Duration, name: String)(op: IO[_]) {
val f = freq.randomize()
//val f = freq
println("schedule effect %s every %s -> %s".format(name, freq, f))
Akka.system.scheduler.schedule(f, f) {
op.unsafePerformIO