Skip to content

Instantly share code, notes, and snippets.

@dyross
Created October 2, 2012 03:05
Show Gist options
  • Save dyross/3815934 to your computer and use it in GitHub Desktop.
Save dyross/3815934 to your computer and use it in GitHub Desktop.
Scaling the Klout API with Scala, Akka, and Play
def blockingAndVerbose: Profile = {
val futureName = name()
val futureScore = score()
val futureFriends = Friends()
val nameResult = Await.result(futureName, 10 seconds)
val scoreResult = Await.result(futureScore, 10 seconds)
val friendsResult = Await.result(futureFriends, 10 seconds)
Profile(nameResult, scoreResult, friendsResult)
}
def nonBlockingComposition: Future[Profile] = {
// NOTE: We declare these up here so they start in parallel. This is required
// because of how for expressions get expanded to maps and flatMaps.
val futureName = name()
val futureScore = score()
val futureFriends = friends()
for {
nameResult <- futureName
scoreResult <- futureScore
friendsResult <- futureFriends
} yield {
Profile(nameResult, scoreResult, friendsResult)
}
}
def name(): Future[String] = Future { "david" }
def score(): Future[Double] = Future { 50.0 }
def friends(): Future[List[Int]] = Future { List(1, 2, 3) }
case class Profile(name: String, score: Double, friends: List[Int])
class MySQLStateService(private var nodes: Set[String]) {
def getHealthyNodes(): Set[String] = nodes
def updateState(node: String, status: Boolean) {
if (status) nodes = nodes + node
else nodes = nodes - node
}
}
val state: MySQLStateService = {
val service = new MySQLStateService(Set.empty)
Zoo.on("/Health/MySQL/node1") {
case NodeUpdated(value) if value == "UP" => state.updateState("node1", true)
case _ => state.updateState("node1", false)
}
service
}
class MySQLStateService(private val agent: Agent[Set[String]]) {
def getHealthyNodes(): Set[String] = agent.apply()
}
val service = {
val agent: Agent[Set[String]] = Agent(Set.empty)
Zoo.on("/Health/MySQL/node1") {
case NodeUpdated(value) if value == "UP" => agent send (prev => prev + "node1")
case _ => agent send (prev => prev - "node1")
}
new MySQLStateService(agent)
}
import com.twitter.zookeeper.ZooKeeperClient
object Zoo {
lazy val zk: ZooKeeperClient = ...
def on(path: String)(callback: NodeStatusChange => Unit) = {
zk watchNode (path, {
(data: Option[Array[Byte]]) =>
data match {
case Some(d) if d.isEmpty =>
callback(NodeUpdated(None))
case Some(d) =>
val value = new String(d)
callback(NodeUpdated(Option(value)))
case None =>
callback(NodeDeleted)
}
})
}
}
@dyross
Copy link
Author

dyross commented Jan 23, 2013

Some.apply(x) does the same thing as Option.apply(x) but has a more restrictive type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment