diff options
Diffstat (limited to 'Server.scala')
-rw-r--r-- | Server.scala | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/Server.scala b/Server.scala new file mode 100644 index 0000000..af4b6b6 --- /dev/null +++ b/Server.scala @@ -0,0 +1,77 @@ +package com.lihaoyi.workbench + +import akka.actor.{ActorRef, Actor, ActorSystem} +import com.typesafe.config.ConfigFactory +import sbt.IO +import spray.routing.SimpleRoutingApp +import akka.actor.ActorDSL._ +import scala.Some +import upickle.{Writer, Json, Js} +import spray.http.{AllOrigins, HttpResponse} +import spray.http.HttpHeaders.`Access-Control-Allow-Origin` +import concurrent.duration._ +class Server(url: String, port: Int, bootSnippet: String) extends SimpleRoutingApp{ + implicit val system = ActorSystem( + "SystemLol", + config = ConfigFactory.load(ActorSystem.getClass.getClassLoader), + classLoader = ActorSystem.getClass.getClassLoader + ) + + val pubSub = actor(new Actor{ + var waitingActor: Option[ActorRef] = None + var queuedMessages = List[Js.Value]() + case object Clear + import system.dispatcher + + system.scheduler.schedule(0 seconds, 10 seconds, self, Clear) + def respond(a: ActorRef, s: String) = { + a ! HttpResponse( + entity = s, + headers = List(`Access-Control-Allow-Origin`(AllOrigins)) + ) + } + def receive = (x: Any) => (x, waitingActor, queuedMessages) match { + case (a: ActorRef, _, Nil) => + // Even if there's someone already waiting, + // a new actor waiting replaces the old one + waitingActor = Some(a) + case (a: ActorRef, None, msgs) => + + respond(a, Json.write(Js.Array(msgs))) + queuedMessages = Nil + case (msg: Js.Array, None, msgs) => + queuedMessages = msg :: msgs + case (msg: Js.Array, Some(a), Nil) => + respond(a, Json.write(Js.Array(Seq(msg)))) + waitingActor = None + case (Clear, Some(a), Nil) => + respond(a, Json.write(Js.Array(Nil))) + waitingActor = None + } + }) + + startServer(url, port) { + get { + path("workbench.js") { + complete { + IO.readStream( + getClass.getClassLoader + .getResourceAsStream("workbench_template.js") + ).replace("<host>", url) + .replace("<port>", port.toString) + .replace("<bootSnippet>", bootSnippet) + } + } ~ + getFromDirectory(".") + } ~ + post { + path("notifications") { ctx => + pubSub ! ctx.responder + } + } + } + + def msg[T: Writer](t: T) = { + pubSub ! upickle.writeJs(t) + } +}
\ No newline at end of file |