From 5f78ca97c56d2eebad265335b2006dd959198599 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 22 Apr 2012 22:09:48 +0200 Subject: [PATCH] Start implementing the bidirectional ping --- app/Cron.scala | 4 ++++ app/memo/BooleanExpiryMemo.scala | 4 ++++ app/site/Hub.scala | 14 +++++++++++++- app/site/Socket.scala | 6 ++---- app/socket/PingMemo.scala | 5 +++++ app/socket/Pinger.scala | 11 +++++++++++ app/socket/model.scala | 2 ++ todo | 4 ++++ 8 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 app/socket/PingMemo.scala create mode 100644 app/socket/Pinger.scala diff --git a/app/Cron.scala b/app/Cron.scala index 90138524ec..13d2a9c79a 100644 --- a/app/Cron.scala +++ b/app/Cron.scala @@ -12,6 +12,10 @@ final class Cron(env: SystemEnv) { implicit val current = env.app implicit val timeout = Timeout(500 millis) + message(5 seconds) { + env.siteHub -> socket.Cleanup + } + message(2 seconds) { env.reporting -> report.Update(env) } diff --git a/app/memo/BooleanExpiryMemo.scala b/app/memo/BooleanExpiryMemo.scala index 4c28ad2294..36a12f8691 100644 --- a/app/memo/BooleanExpiryMemo.scala +++ b/app/memo/BooleanExpiryMemo.scala @@ -16,6 +16,10 @@ abstract class BooleanExpiryMemo(timeout: Int) { cache.put(key, true) } + def putUnsafe(key: String): Unit = { + cache.put(key, true) + } + def putAll(keys: Iterable[String]): IO[Unit] = io { keys map { cache.put(_, true) } } diff --git a/app/site/Hub.scala b/app/site/Hub.scala index 9645c29dec..06d2e5f7bf 100644 --- a/app/site/Hub.scala +++ b/app/site/Hub.scala @@ -10,22 +10,34 @@ import play.api.libs.iteratee._ final class Hub extends Actor { private var members = Map.empty[String, Member] + private val pinger = new Pinger def receive = { + case Ping(uid) ⇒ { + members get uid foreach { _.channel push Util.pong } + } + + case Cleanup ⇒ members.keys filterNot pingers.get foreach { uid ⇒ + self ! Quit(uid) + } + case WithUsernames(op) ⇒ op(usernames).unsafePerformIO case Join(uid, username) ⇒ { val channel = new LilaEnumerator[JsValue](Nil) members = members + (uid -> Member(channel, username)) sender ! Connected(channel) + pingers putUnsafe uid } case NbMembers ⇒ notifyAll("n", JsNumber(members.size)) case GetNbMembers ⇒ sender ! members.size - case Quit(uid) ⇒ { members = members - uid } + case Quit(uid) ⇒ { + members = members - uid + } } private def notifyAll(t: String, data: JsValue) { diff --git a/app/site/Socket.scala b/app/site/Socket.scala index b865178a6c..7101d86196 100644 --- a/app/site/Socket.scala +++ b/app/site/Socket.scala @@ -11,7 +11,7 @@ import play.api.libs.concurrent._ import scalaz.effects._ import RichJs._ -import socket.Util +import socket.{ Util, Ping } final class Socket(hub: ActorRef) { @@ -26,9 +26,7 @@ final class Socket(hub: ActorRef) { case Connected(channel) ⇒ val iteratee = Iteratee.foreach[JsValue] { e ⇒ e str "t" match { - case Some("p") ⇒ { - channel push Util.pong - } + case Some("p") ⇒ hub ! Ping(uid) case _ ⇒ } Unit diff --git a/app/socket/PingMemo.scala b/app/socket/PingMemo.scala new file mode 100644 index 0000000000..c09f96a729 --- /dev/null +++ b/app/socket/PingMemo.scala @@ -0,0 +1,5 @@ +package lila +package socket + +// keys = uid +final class PingMemo(timeout: Int) extends BooleanExpiryMemo(timeout) diff --git a/app/socket/Pinger.scala b/app/socket/Pinger.scala new file mode 100644 index 0000000000..8ab2ac797c --- /dev/null +++ b/app/socket/Pinger.scala @@ -0,0 +1,11 @@ +package lila +package socket + +final class Pinger { + + private val uids = new memo.PingMemo(20 * 1000) + + def apply(uid: String) { + uids putUnsafe uid + } +} diff --git a/app/socket/model.scala b/app/socket/model.scala index 8c1c8ebd28..126c5bb0ce 100644 --- a/app/socket/model.scala +++ b/app/socket/model.scala @@ -3,3 +3,5 @@ package socket case object Close case object GetNbMembers +case class Ping(uid: String) +case object Cleanup diff --git a/todo b/todo index 1903ac6410..5066572167 100644 --- a/todo +++ b/todo @@ -1,2 +1,6 @@ ping nbm back button +accept rematch -> end up as spectator of the new game +extract chess +chat ban +wrong number of players