Skip to content

Commit

Permalink
koans compile in a seperate process with communication via rabbitmq
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesward committed Mar 31, 2012
1 parent 75bb672 commit c6b408e
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 39 deletions.
19 changes: 10 additions & 9 deletions .gitignore
@@ -1,9 +1,10 @@
logs /logs
project/project /project/project
project/target /project/target
target /target
tmp /tmp
.history /.history
dist /dist
.idea /.idea
*.iml /*.iml
/out
20 changes: 20 additions & 0 deletions app/Global.scala
@@ -0,0 +1,20 @@
import com.rabbitmq.client.AMQP.BasicProperties
import com.rabbitmq.client.{GetResponse, Channel, ConnectionFactory}
import messaging.MessageBus
import play.api.GlobalSettings

import play.api.Application

object Global extends GlobalSettings {

override def onStart(app: Application) {

app.configuration.getString("rabbitmq.uri") map { uri =>
MessageBus.setup(uri)
} getOrElse {
sys.error("No rabbitmq.uri specified")
}

}

}
38 changes: 17 additions & 21 deletions app/controllers/Application.scala
@@ -1,16 +1,17 @@
package controllers package controllers


import play.api.mvc._ import scala.collection.mutable.Map
import play.api.data._
import play.api.data.Forms._
import views.html


import com.twitter.util.Eval import messaging.MessageBus
import support.KoanSuite import com.rabbitmq.client.RpcClient
import org.scalatest.{Filter, Stopper, Tracker} import koanrunner.TestResult
import koanrunner.{TestResult, KoanReporter}
import play.api.mvc.Controller
import play.api.mvc.Action
import play.api.data.Form
import play.api.data.Forms.{single, nonEmptyText}
import com.codahale.jerkson.Json


import scala.collection.mutable.Map


object Application extends Controller { object Application extends Controller {


Expand All @@ -28,20 +29,15 @@ object Application extends Controller {
implicit request => implicit request =>
scalaCodeForm.bindFromRequest.value map { scalaCodeForm.bindFromRequest.value map {
case (inputScala) => { case (inputScala) => {
val outputScala = doEval(inputScala) // send message to rabbitmq
Ok(html.output(outputScala)) val rpcClient = new RpcClient(MessageBus.channel, MessageBus.exchangeName, MessageBus.routingKey, MessageBus.timeout)
} val response = rpcClient.stringCall(inputScala)
} getOrElse BadRequest
}

def doEval(scalaCode: String) = {
val suite = Eval[KoanSuite](scalaCode)

val results = Map[String, TestResult]()


suite.run(None, new KoanReporter(results), new Stopper {}, Filter(), scala.collection.immutable.Map[String, Any](), None, new Tracker) val testResults = Json.parse[Map[String, TestResult]](response)


results Ok(views.html.output(testResults))
}
} getOrElse BadRequest
} }


} }
41 changes: 41 additions & 0 deletions app/koanrunner/KoanRunner.scala
@@ -0,0 +1,41 @@
package koanrunner

import messaging.MessageBus
import util.Properties
import com.rabbitmq.client.StringRpcServer
import support.KoanSuite
import com.twitter.util.Eval
import org.scalatest.{Filter, Tracker, Stopper}
import com.codahale.jerkson.Json

import scala.collection.mutable.Map

object KoanRunner extends App {

Properties.envOrNone("RABBITMQ_URL") map { uri =>

MessageBus.setup(uri)

val server: StringRpcServer = new StringRpcServer(MessageBus.channel, MessageBus.queueName) {
override def handleStringCall(request: String) = {
println("received: " + request)

val suite = Eval[KoanSuite](request)

val results = Map[String, TestResult]()

suite.run(None, new KoanReporter(results), new Stopper {}, Filter(), scala.collection.immutable.Map[String, Any](), None, new Tracker)

val json = Json.generate(results)
println("returning: " + json)
json
}
}

server.mainloop()

} getOrElse {
sys.error("RABBITMQ_URL environment variable not found")
}

}
28 changes: 28 additions & 0 deletions app/messaging/MessageBus.scala
@@ -0,0 +1,28 @@
package messaging

import com.rabbitmq.client.AMQP.BasicProperties
import com.rabbitmq.client.{RpcClient, ConnectionFactory, StringRpcServer, Channel}


object MessageBus {

val exchangeName: String = "koan-exchange"
val routingKey: String = "koan-routing-key"
val exchangeType: String = "direct"
val timeout = 20000

var channel: Channel = _
var queueName: String = _

def setup(uri: String) {
val factory = new ConnectionFactory()
factory.setUri(uri)

val conn = factory.newConnection()
channel = conn.createChannel()
channel.exchangeDeclare(exchangeName, exchangeType, true)
queueName = channel.queueDeclare().getQueue
channel.queueBind(queueName, exchangeName, routingKey)
}

}
1 change: 1 addition & 0 deletions conf/application.conf
Expand Up @@ -45,3 +45,4 @@ logger.play=INFO
# Logger provided to your application: # Logger provided to your application:
logger.application=DEBUG logger.application=DEBUG


rabbitmq.uri="amqp://guest:guest@localhost:5672/%2f"
19 changes: 10 additions & 9 deletions project/Build.scala
Expand Up @@ -4,16 +4,17 @@ import PlayProject._


object ApplicationBuild extends Build { object ApplicationBuild extends Build {


val appName = "scalaKoansOnline" val appName = "scalaKoansOnline"
val appVersion = "1.0-SNAPSHOT" val appVersion = "1.0-SNAPSHOT"


val appDependencies = Seq( val appDependencies = Seq(
"com.twitter" % "util-eval" % "3.0.0", "com.twitter" % "util-eval" % "3.0.0",
"org.scalatest" %% "scalatest" % "1.7.1" "org.scalatest" %% "scalatest" % "1.7.1",
) "com.rabbitmq" % "amqp-client" % "2.8.1"
)


val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings( val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
// Add your own project settings here
) )


} }

1 comment on commit c6b408e

@radonsky
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job, James!

Please sign in to comment.